www/apps/book/app/learn/debugging-and-testing/debug-workflows/page.mdx
import { Table, Prerequisites, CodeTabs, CodeTab } from "docs-ui"
export const metadata = {
title: ${pageNumber} Debug Workflows,
}
In this chapter, you'll learn about the different ways you can debug workflows in Medusa.
Debugging workflows is essential to ensure your custom features work as expected. It helps you identify unexpected issues and bugs in your workflow logic.
There are several ways to debug workflows in Medusa:
<Table> <Table.Header> <Table.Row> <Table.HeaderCell> Approach </Table.HeaderCell> <Table.HeaderCell> When to Use </Table.HeaderCell> </Table.Row> </Table.Header> <Table.Body> <Table.Row> <Table.Cell> [Write integration tests](#approach-1-write-integration-tests) </Table.Cell> <Table.Cell> To ensure your workflow produces the expected results and handles edge cases. </Table.Cell> </Table.Row> <Table.Row> <Table.Cell> [Add breakpoints](#approach-2-add-breakpoints) </Table.Cell> <Table.Cell> To inspect specific steps in your workflow and understand the data flow. </Table.Cell> </Table.Row> <Table.Row> <Table.Cell> [Log messages](#approach-3-log-messages) </Table.Cell> <Table.Cell> To check values during execution with minimal overhead. </Table.Cell> </Table.Row> <Table.Row> <Table.Cell> [View Workflow Executions in Medusa Admin](#approach-4-monitor-workflow-executions-in-medusa-admin) </Table.Cell> <Table.Cell> To monitor stored workflow executions and long-running workflows, especially in production environments. </Table.Cell> </Table.Row> </Table.Body> </Table>Integration tests run your workflow in a controlled environment to verify its behavior and outcome. By writing integration tests, you ensure your workflow produces the expected results and handles edge cases.
It's recommended to always write integration tests for your workflows. This helps you catch issues early and ensures your custom logic works as intended.
Refer to the Integration Tests chapter to learn how to write integration tests for your workflows and find examples of testing workflows.
Breakpoints allow you to pause workflow execution at specific steps and inspect the data. They're useful for understanding the data flow in your steps and identifying issues.
Use breakpoints when you need to debug specific steps in your workflow, rather than the entire workflow. You can verify that the step is behaving as expected and is producing the correct output.
Since Medusa stores an internal representation of the workflow constructor on application startup, breakpoints within the workflow's constructor won't work during execution. Learn more in the Data Manipulation chapter.
Instead, you can add breakpoints in:
transform callback function of a step.For example:
<CodeTabs group="debug-type"> <CodeTab label="Step Function" value="step-function">import {
createStep,
createWorkflow,
StepResponse,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
const step1 = createStep(
"step-1",
async () => {
// Add a breakpoint here to inspect the message
const message = "Hello from step 1!"
return new StepResponse(
message
)
}
)
export const myWorkflow = createWorkflow(
"my-workflow",
() => {
const response = step1()
return new WorkflowResponse({
response,
})
}
)
import {
createStep,
createWorkflow,
StepResponse,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
const step1 = createStep(
"step-1",
async () => {
const message = "Hello from step 1!"
return new StepResponse(
message
)
},
async () => {
// Add a breakpoint here to inspect the compensation logic
console.log("Compensating step 1")
}
)
const step2 = createStep(
"step-2",
async () => {
throw new Error("This is an error in step 2")
}
)
export const myWorkflow = createWorkflow(
"my-workflow",
() => {
const response = step1()
step2()
return new WorkflowResponse({
response,
})
}
)
import {
createStep,
createWorkflow,
StepResponse,
WorkflowResponse,
transform,
} from "@medusajs/framework/workflows-sdk"
const step1 = createStep(
"step-1",
async () => {
const message = "Hello from step 1!"
return new StepResponse(
message
)
}
)
export const myWorkflow = createWorkflow(
"my-workflow",
() => {
const response = step1()
const transformedMessage = transform(
{ response },
(data) => {
// Add a breakpoint here to inspect the transformed data
const upperCase = data.response.toUpperCase()
return upperCase
}
)
return new WorkflowResponse({
response: transformedMessage,
})
}
)
If your code editor supports adding breakpoints, you can add them in your step and compensation functions, or the transform callback function. When the workflow execution reaches the breakpoint, your code editor will pause execution, allowing you to inspect the data and walk through the code.
If you're using VS Code or Cursor, learn how to add breakpoints in the VS Code documentation. For other code editors, refer to their respective documentation.
Logging messages is a simple yet effective way to debug code. By logging messages, you can check values during execution with minimal overhead.
Use logging when debugging workflows and you want to check values during execution without the overhead of setting up breakpoints.
Logging is also useful when you want to verify variable values between steps or in a transform callback function.
Since Medusa stores an internal representation of the workflow constructor on application startup, you can't directly log messages in the workflow's constructor.
Instead, you can log messages in:
transform callback function of a step.You can log messages with console.log. In step and compensation functions, you can also use the Logger to log messages with different log levels (info, warn, error).
For example:
<CodeTabs group="debug-type"> <CodeTab label="Step Function" value="step-function">import {
createStep,
createWorkflow,
StepResponse,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
const step1 = createStep(
"step-1",
async ({}, { container }) => {
const logger = container.resolve("logger")
const message = "Hello from step 1!"
logger.info(`Step 1 output: ${message}`)
return new StepResponse(
message
)
}
)
export const myWorkflow = createWorkflow(
"my-workflow",
() => {
const response = step1()
return new WorkflowResponse({
response,
})
}
)
import {
createStep,
createWorkflow,
StepResponse,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
const step1 = createStep(
"step-1",
async ({}, { container }) => {
const logger = container.resolve("logger")
const message = "Hello from step 1!"
logger.info(`Step 1 output: ${message}`)
return new StepResponse(
message
)
},
async (_, { container }) => {
const logger = container.resolve("logger")
logger.warn("Compensating step 1")
}
)
export const myWorkflow = createWorkflow(
"my-workflow",
() => {
const response = step1()
return new WorkflowResponse({
response,
})
}
)
import {
createStep,
createWorkflow,
StepResponse,
WorkflowResponse,
transform,
} from "@medusajs/framework/workflows-sdk"
const step1 = createStep(
"step-1",
async () => {
const message = "Hello from step 1!"
return new StepResponse(
message
)
}
)
export const myWorkflow = createWorkflow(
"my-workflow",
() => {
const response = step1()
const transformedMessage = transform(
{ response },
(data) => {
const upperCase = data.response.toUpperCase()
console.log("Transformed Data:", upperCase)
return upperCase
}
)
return new WorkflowResponse({
response: transformedMessage,
})
}
)
If you execute the workflow, you'll see the logged message in your console.
<Note>Learn more about logging in the Logger chapter.
</Note>The Medusa Admin has a Workflows settings page that provides a user-friendly interface to view stored workflow executions.
Use the Medusa Admin to monitor stored workflow executions when debugging unexpected issues and edge cases, especially in production environments and long-running workflows that run in the background.
By viewing the workflow executions through the Medusa Admin, you can:
The Workflows settings page in the Medusa Admin shows you the history of stored workflow executions only. Workflow executions are stored if a workflow is long-running, or if the store and retentionTime options are set on the workflow.
For example, to store workflow executions:
<Prerequisites items={[ { text: "Redis Workflow Engine must be installed and configured.", link: "!resources!/infrastructure-modules/workflow-engine/redis" } ]} />
import {
createStep,
createWorkflow,
StepResponse,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
const step1 = createStep(
"step-1",
async () => {
const message = "Hello from step 1!"
return new StepResponse(
message
)
}
)
export const myWorkflow = createWorkflow(
{
name: "my-workflow",
retentionTime: 99999,
store: true,
},
() => {
const response = step1()
return new WorkflowResponse({
response,
})
}
)
Refer to the Store Workflow Executions chapter to learn more.
</Note>You can view all executions of this workflow in the Medusa Admin under the Workflows settings page. Each execution will show you the status, input, and output data.