www/apps/resources/app/integrations/guides/sentry/page.mdx
import { Card, Prerequisites, Details, WorkflowDiagram } from "docs-ui" import { Github, PlaySolid } from "@medusajs/icons"
export const metadata = {
title: Integrate Sentry (Instrumentation) with Medusa,
}
In this tutorial, you'll learn how to integrate Sentry with your Medusa application to monitor performance and track errors effectively.
When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. An essential part of building customizations is tracking errors in them and ensuring they have good performance.
Medusa facilitates error tracking and performance monitoring by integrating with instrumentation tools like Sentry. Sentry provides real-time tracking of errors and performance issues in your application, allowing you to identify and fix them quickly.
In this tutorial, you'll integrate Sentry with Medusa to monitor your application's performance and errors.
By following this tutorial, you'll learn how to:
You can follow this tutorial whether you're new to Medusa or an advanced Medusa developer.
<Card title="Example Repository" text="Find the full code of the guide in this repository." href="https://github.com/medusajs/examples/tree/main/sentry-integration" icon={Github} />
<Prerequisites items={[ { text: "Node.js v20+", link: "https://nodejs.org/en/download" }, { text: "Git CLI tool", link: "https://git-scm.com/downloads" }, { text: "PostgreSQL", link: "https://www.postgresql.org/download/" } ]} />
Start by installing the Medusa application on your machine with the following command:
npx create-medusa-app@latest
First, you'll be asked for the project's name. Then, when prompted about installing the Next.js Starter Storefront, choose "Yes."
Afterwards, the installation process will start, which will install the Medusa application as a monorepository in a directory with your project's name. The backend is installed in the apps/backend directory, and the Next.js Starter Storefront is installed in the apps/storefront directory.
Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard.
<Note title="Ran into Errors?">Check out the troubleshooting guides for help.
</Note> <Note>In this guide, all file paths of backend customizations are relative to the apps/backend directory of your Medusa project.
Medusa supports instrumentation and reporting through OpenTelemetry, which allows you to integrate with various monitoring tools, including Sentry. This also gives you the flexibility to switch between different monitoring tools without changing your codebase.
In this step, you'll set up instrumentation in your Medusa application using Sentry.
<Note>Refer to the Instrumentation documentation for more details on how to set up instrumentation in Medusa.
</Note>To set up instrumentation in Medusa, you need to install the dependencies necessary for the monitoring tool you want to use, which is Sentry in this case.
So, run the following command to install the necessary Sentry dependencies:
npm install @sentry/node @opentelemetry/api @opentelemetry/exporter-trace-otlp-grpc @sentry/opentelemetry-node @opentelemetry/[email protected] @opentelemetry/[email protected] @opentelemetry/[email protected]
Now that you have the necessary dependencies installed, you need to configure instrumentation in your Medusa application.
You can configure instrumentation in a special instrumentation.ts file at the root of your Medusa application. The Medusa application automatically loads this file when it starts.
You should already have a file named instrumentation.ts in your Medusa application with commented-out code. Replace the file's content with the following:
import Sentry from "@sentry/node"
import otelApi from "@opentelemetry/api"
import { registerOtel } from "@medusajs/medusa"
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc"
import {
SentrySpanProcessor,
SentryPropagator,
} from "@sentry/opentelemetry-node"
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
// @ts-ignore
instrumenter: "otel",
})
otelApi.propagation.setGlobalPropagator(new SentryPropagator())
export function register() {
registerOtel({
serviceName: "medusa",
spanProcessors: [new SentrySpanProcessor()],
traceExporter: new OTLPTraceExporter(),
instrument: {
http: true,
workflows: true,
query: true,
db: true,
},
})
}
You first initialize Sentry with your Data Source Name (DSN), which you'll retrieve and set as an environment variable soon. You also set the tracesSampleRate to 1.0, which enables tracing in your Sentry project.
Next, you set the global propagator to Sentry's propagator, which allows Sentry to propagate trace context across your application.
Finally, you export a register function that registers OpenTelemetry. It uses the registerOtel function from Medusa, which accepts OpenTelemetry configurations with the following custom Medusa options:
serviceName: The name of your service, which you set to "medusa". You can change it to a more descriptive name if needed.instrument: An object that specifies what to trace in your Medusa application. You enable tracing for HTTP requests, workflows, Query usages, and database operations by setting their respective properties to true.You can add any additional configurations to either Sentry or OpenTelemetry as needed for your use case.
The final piece to get the Sentry integration working is to set up a Sentry project and get your DSN. The DSN is a unique identifier for your Sentry project that allows your Medusa application to send error and performance data to Sentry.
To set up a Sentry project:
You can skip onboarding or the next steps for now. You'll test out the integration in the next step.
Then, add the following environment variable to your .env file in your Medusa application:
SENTRY_DSN=your_sentry_dsn_here
Replace your_sentry_dsn_here with the DSN you copied from Sentry.
You can now test the integration to ensure operations are traced in Sentry.
First, start your Medusa application by running the following command in your apps/backend directory:
npm run dev
You'll find in the terminal the following message:
info: OTEL registered
This message indicates that OpenTelemetry has been successfully registered and instrumentation is set up successfully.
Then, open your Medusa Admin dashboard in your browser at http://localhost:9000/app and log in with the user you created earlier.
You can already find the database, workflow executions, and HTTP requests traced in your Sentry project:
If you click on a trace, you can see more details about the trace. For example, if you click on an HTTP request trace, you can see the middlewares and workflows executed, the time taken for each operation, the status of the request, and more.
Tracing also works for your custom API routes, workflow executions, Query usages, and database operations.
In this section, you'll test it by creating a custom API route that throws an error. For now, you'll only view its tracing in Sentry. Later, you'll configure capturing HTTP request errors in Sentry.
<Note title="Tip">An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts.
</Note>An API route is created in a route.ts file under a sub-directory of the src/api directory. The path of the API route is the file's path relative to src/api.
So, to create an API route at the path /test-sentry, create the file src/api/test-sentry/route.ts with the following content:
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { MedusaError } from "@medusajs/framework/utils"
export async function GET(
req: MedusaRequest,
res: MedusaResponse
) {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"This is a test error for Sentry integration."
)
}
Since you export a GET route handler function, you expose a GET API route at /test-sentry. The route handler function accepts two parameters:
In the route handler, you throw a MedusaError with a custom message. This error will be returned as a response to the request. Later, when you configure error capturing in Sentry, this error will be captured and displayed in the Sentry dashboard.
To test the API route, make sure your Medusa application is running, then go to http://localhost:9000/test-sentry in your browser or use curl:
curl http://localhost:9000/test-sentry
You'll receive the following error in the response:
{
"type": "unexpected_state",
"message": "This is a test error for Sentry integration."
}
If you refresh the Tracing page in your Sentry dashboard, you should see a new trace for the /test-sentry API route.
It may take a few seconds for the trace to appear in Sentry, so if you don't see it immediately, wait a bit and refresh the page.
</Note>If you click on the Trace ID, you'll see the details of the trace.
In the previous step, you tested tracing in Sentry by creating a custom API route that throws an error. However, the error was not captured by Sentry. So, you couldn't see the error details in the Sentry dashboard or get notified about it.
In this step, you'll capture HTTP request errors in Sentry. You'll do that by customizing Medusa's default error handler that is used to handle errors in API routes.
<Note>Refer to the Throwing and Handling Errors guide to learn more about Medusa's default error handling behavior.
</Note>To customize the error handler, create the file src/api/middlewares.ts with the following content:
export const errorHandlerHighlights = [ ["20", "captureException", "Capture the error in Sentry."], ["21", "originalErrorHandler", "Call Medusa's default error handler."], ]
import {
defineMiddlewares,
errorHandler,
MedusaNextFunction,
MedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { MedusaError } from "@medusajs/framework/utils"
import * as Sentry from "@sentry/node"
const originalErrorHandler = errorHandler()
export default defineMiddlewares({
errorHandler: (
error: MedusaError | any,
req: MedusaRequest,
res: MedusaResponse,
next: MedusaNextFunction
) => {
Sentry.captureException(error)
return originalErrorHandler(error, req, res, next)
},
})
You export the defineMiddlewares function that allows you to apply middlewares and customize Medusa's default error handler.
The function accepts an object with the errorHandler property, whose value is a custom function that handles errors thrown in API routes.
In the custom error handler, you first capture the error in Sentry using Sentry.captureException(error). This allows Sentry to track the error and its context.
Then, you call the original error handler function that Medusa uses to handle errors in API routes. By using this function, you retain Medusa's default error handling behavior of returning the error response to the client.
To test out error capturing in Sentry, start the Medusa application if it's not already running:
npm run dev
Then, send a GET request to the /test-sentry API route you created earlier:
curl http://localhost:9000/test-sentry
You'll receive the same error response as before:
{
"type": "unexpected_state",
"message": "This is a test error for Sentry integration."
}
If you check the tracing page in your Sentry dashboard, you'll see a new trace for the /test-sentry API route. Click on it to view the details.
You'll find in the tracing page the thrown error highlighted in red, indicating that it was captured by Sentry.
If you click on the error, you can view more details about it, such as its stack trace, how many times it occurred, its breadcrumbs, and more.
By capturing HTTP request errors in Sentry, you can now monitor and track errors in your Medusa application effectively. You can also set up alerts in Sentry to get notified about critical issues and handle them promptly.
You've now integrated Sentry with your Medusa application. You can continue using Sentry to monitor your application's performance and track errors.
You can also expand on your Sentry integration by enabling more features, such as:
If you're new to Medusa, check out the main documentation, where you'll get a more in-depth understanding of all the concepts you've used in this guide and more.
To learn more about the commerce features that Medusa provides, check out Medusa's Commerce Modules.
If you encounter issues during your development, check out the troubleshooting guides.
If you encounter issues not covered in the troubleshooting guides: