diff --git a/www/apps/book/app/learn/debugging-and-testing/instrumentation/page.mdx b/www/apps/book/app/learn/debugging-and-testing/instrumentation/page.mdx index f04312b8ed..15e8f0ce5d 100644 --- a/www/apps/book/app/learn/debugging-and-testing/instrumentation/page.mdx +++ b/www/apps/book/app/learn/debugging-and-testing/instrumentation/page.mdx @@ -8,7 +8,15 @@ export const metadata = { In this chapter, you'll learn about observability in Medusa and how to configure instrumentation with OpenTelemetry. -## Observability with OpenTelemtry +## What is Instrumentation? + +Instrumentation is the collection of data about your application's performance and errors. It helps you debug issues, monitor performance, and gain insights into how your application behaves in production. + +Instrumentation and observability are crucial as you build customizations in your application. They allow you to optimize performance, identify bottlenecks, and ensure your application runs smoothly. + +--- + +## Instrumentation and Observability with OpenTelemetry Medusa uses [OpenTelemetry](https://opentelemetry.io/) for instrumentation and reporting. When configured, it reports traces for: @@ -158,3 +166,9 @@ Trace span names start with the following keywords based on what it's reporting: - `step:` when reporting a step in a workflow execution. - `query.graph:` when reporting Query usages. - `pg.query:` when reporting database queries and operations. + +--- + +## Useful Links + +- [Integrate Sentry with Medusa](!resources!/integrations/guides/sentry) \ No newline at end of file diff --git a/www/apps/book/generated/edit-dates.mjs b/www/apps/book/generated/edit-dates.mjs index cd7b31760a..64de1af14f 100644 --- a/www/apps/book/generated/edit-dates.mjs +++ b/www/apps/book/generated/edit-dates.mjs @@ -70,7 +70,7 @@ export const generatedEditDates = { "app/learn/fundamentals/modules/db-operations/page.mdx": "2025-04-25T14:26:25.000Z", "app/learn/fundamentals/modules/multiple-services/page.mdx": "2025-03-18T15:11:44.632Z", "app/learn/fundamentals/modules/page.mdx": "2025-03-18T07:51:09.049Z", - "app/learn/debugging-and-testing/instrumentation/page.mdx": "2025-02-24T08:12:53.132Z", + "app/learn/debugging-and-testing/instrumentation/page.mdx": "2025-06-16T10:40:52.922Z", "app/learn/fundamentals/api-routes/additional-data/page.mdx": "2025-04-17T08:50:17.036Z", "app/learn/fundamentals/workflows/variable-manipulation/page.mdx": "2025-04-24T13:14:43.967Z", "app/learn/customization/custom-features/api-route/page.mdx": "2024-12-09T10:39:30.046Z", diff --git a/www/apps/book/generated/sidebar.mjs b/www/apps/book/generated/sidebar.mjs index c54006601b..a776f67aa3 100644 --- a/www/apps/book/generated/sidebar.mjs +++ b/www/apps/book/generated/sidebar.mjs @@ -1128,7 +1128,18 @@ export const generatedSidebars = [ "type": "link", "path": "/learn/debugging-and-testing/instrumentation", "title": "Instrumentation", - "children": [], + "children": [ + { + "loaded": true, + "isPathHref": true, + "type": "ref", + "path": "/resources/integrations/guides/sentry", + "title": "Guide: Sentry", + "children": [], + "chapterTitle": "7.4.1. Guide: Sentry", + "number": "7.4.1." + } + ], "chapterTitle": "7.4. Instrumentation", "number": "7.4." }, diff --git a/www/apps/book/public/llms-full.txt b/www/apps/book/public/llms-full.txt index 46a2b47859..e099807355 100644 --- a/www/apps/book/public/llms-full.txt +++ b/www/apps/book/public/llms-full.txt @@ -3337,7 +3337,15 @@ To learn more about plugins and how to create them, refer to [this chapter](http In this chapter, you'll learn about observability in Medusa and how to configure instrumentation with OpenTelemetry. -## Observability with OpenTelemtry +## What is Instrumentation? + +Instrumentation is the collection of data about your application's performance and errors. It helps you debug issues, monitor performance, and gain insights into how your application behaves in production. + +Instrumentation and observability are crucial as you build customizations in your application. They allow you to optimize performance, identify bottlenecks, and ensure your application runs smoothly. + +*** + +## Instrumentation and Observability with OpenTelemetry Medusa uses [OpenTelemetry](https://opentelemetry.io/) for instrumentation and reporting. When configured, it reports traces for: @@ -3442,6 +3450,12 @@ Trace span names start with the following keywords based on what it's reporting: - `query.graph:` when reporting Query usages. - `pg.query:` when reporting database queries and operations. +*** + +## Useful Links + +- [Integrate Sentry with Medusa](https://docs.medusajs.com/resources/integrations/guides/sentry/index.html.md) + # Logging @@ -54678,7 +54692,7 @@ export async function POST( } ``` -Since you export a `POST` route handler function, you expose an `API` route at `/admin/algolia/sync`. The route handler function accepts two parameters: +Since you export a `POST` route handler function, you expose a `POST` API route at `/admin/algolia/sync`. The route handler function accepts two parameters: 1. A request object with details and context on the request, such as body parameters or authenticated user details. 2. A response object to manipulate and send the response. @@ -62886,6 +62900,364 @@ If you encounter issues not covered in the troubleshooting guides: 3. Contact the [sales team](https://medusajs.com/contact/) to get help from the Medusa team. +# 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](https://sentry.io/). 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. + +## Summary + +By following this tutorial, you'll learn how to: + +- Install and set up Medusa. +- Set up instrumentation with Sentry. You'll trace HTTP requests, workflows, Query usages, and database operations. +- Capture HTTP request errors in Sentry. +- Test monitoring and error tracking. + +You can follow this tutorial whether you're new to Medusa or an advanced Medusa developer. + +![Diagram showcasing what is traced in Sentry](https://res.cloudinary.com/dza7lstvk/image/upload/v1750069550/Medusa%20Resources/sentry-integration_xb2ior.jpg) + +[Example Repository](https://github.com/medusajs/examples/tree/main/sentry-integration): Find the full code of the guide in this repository. + +*** + +## Step 1: Install a Medusa Application + +### Prerequisites + +- [Node.js v20+](https://nodejs.org/en/download) +- [Git CLI tool](https://git-scm.com/downloads) +- [PostgreSQL](https://www.postgresql.org/download/) + +Start by installing the Medusa application on your machine with the following command: + +```bash +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](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." + +Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. + +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). + +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. + +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. + +*** + +## Step 2: Set Up Instrumentation with Sentry + +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. + +Refer to the [Instrumentation](https://docs.medusajs.com/docs/learn/debugging-and-testing/instrumentation/index.html.md) documentation for more details on how to set up instrumentation in Medusa. + +### a. Install Instrumentation Dependencies + +To set up instrumentation in Medusa, you need to install the necessary OpenTelemetry dependencies. + +In your Medusa application's directory, run the following command: + +```bash npm2yarn +npm install @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/sdk-trace-node @opentelemetry/instrumentation-pg +``` + +Then, 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: + +```bash npm2yarn +npm install @sentry/node @opentelemetry/api @opentelemetry/exporter-trace-otlp-grpc @sentry/opentelemetry-node +``` + +### b. Configure Instrumentation + +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: + +```ts title="instrumentation.ts" +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](https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_sdk-node.NodeSDKConfiguration.html) 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. + +### c. Set Up a Sentry Project + +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: + +1. [Log in or sign up](https://sentry.io/signup/) to Sentry. +2. In your Sentry dashboard, if you're new to Sentry, click the "Start" button. Otherwise, go to Projects from the sidebar and click the "Create Project" button. +3. In the "Select Platform" step, select "Node.js" as the platform, then select "Node, Vanilla" in the pop-up. + +![Screenshot of the pop up with Node, Vanilla selected](https://res.cloudinary.com/dza7lstvk/image/upload/v1750064385/Medusa%20Resources/CleanShot_2025-06-16_at_10.29.29_2x_dkmwtn.png) + +4. In the "Configure Node.js SDK" step, you can find your DSN in the second code block. Copy the DSN, as you'll need it in the next step. + +![Screenshot of the Configure Node.js SDK step with the DSN highlighted](https://res.cloudinary.com/dza7lstvk/image/upload/v1750064502/Medusa%20Resources/CleanShot_2025-06-16_at_12.00.36_2x_wlc0o1.png) + +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: + +```shell title=".env" +SENTRY_DSN=your_sentry_dsn_here +``` + +Replace `your_sentry_dsn_here` with the DSN you copied from Sentry. + +### Test Tracing in 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 Medusa application's directory: + +```bash npm2yarn +npm run dev +``` + +You'll find in the terminal the following message: + +```bash +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: + +1. In your Sentry dashboard, go to Explore → Traces from the sidebar. +2. You'll find a list of traces on this page, including HTTP requests made to log in to the Medusa Admin dashboard. + +![Sentry dashboard with traces listed](https://res.cloudinary.com/dza7lstvk/image/upload/v1750065824/Medusa%20Resources/CleanShot_2025-06-16_at_12.23.29_2x_at87kq.png) + +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. + +![Sentry trace details with HTTP request and workflow execution](https://res.cloudinary.com/dza7lstvk/image/upload/v1750065922/Medusa%20Resources/CleanShot_2025-06-16_at_12.25.10_2x_w8jzgl.png) + +### Test Tracing for Customizations + +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. + +An [API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) is an endpoint that exposes commerce features to external applications and clients, such as storefronts. + +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: + +```ts title="src/api/test-sentry/route.ts" +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: + +1. A request object with details and context on the request, such as body parameters. +2. A response object to manipulate and send the response. + +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`: + +```bash +curl http://localhost:9000/test-sentry +``` + +You'll receive the following error in the response: + +```json +{ + "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. + +![Trace dashboard with the test API route trace](https://res.cloudinary.com/dza7lstvk/image/upload/v1750066376/Medusa%20Resources/CleanShot_2025-06-16_at_12.32.37_2x_uox6r1.png) + +If you click on the Trace ID, you'll see the details of the trace. + +![Sentry trace details with error breadcrumbs](https://res.cloudinary.com/dza7lstvk/image/upload/v1750066493/Medusa%20Resources/CleanShot_2025-06-16_at_12.34.33_2x_unzktq.png) + +*** + +## Step 3: Capture HTTP Request Errors in Sentry + +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. + +Refer to the [Throwing and Handling Errors](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/errors/index.html.md) guide to learn more about Medusa's default error handling behavior. + +To customize the error handler, create the file `src/api/middlewares.ts` with the following content: + +```ts title="src/api/middlewares.ts" highlights={errorHandlerHighlights} +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. + +### Test Error Capturing in Sentry + +To test out error capturing in Sentry, start the Medusa application if it's not already running: + +```bash npm2yarn +npm run dev +``` + +Then, send a `GET` request to the `/test-sentry` API route you created earlier: + +```bash +curl http://localhost:9000/test-sentry +``` + +You'll receive the same error response as before: + +```json +{ + "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. + +![Sentry trace details with error message](https://res.cloudinary.com/dza7lstvk/image/upload/v1750347022/Medusa%20Resources/CleanShot_2025-06-19_at_18.29.57_2x_aenvrd.png) + +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. + +![Error details in Sentry](https://res.cloudinary.com/dza7lstvk/image/upload/v1750347022/Medusa%20Resources/CleanShot_2025-06-19_at_18.30.07_2x_oz5y9e.png) + +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. + +*** + +## Next Steps + +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: + +- [Alerts](https://docs.sentry.io/product/alerts/) to get notified about critical issues in your application. You can receive alerts via email, Slack, or other channels. +- [Profiling](https://docs.sentry.io/platforms/javascript/guides/nextjs/profiling/node/) to analyze your application's performance and identify bottlenecks. +- [User feedback](https://docs.sentry.io/product/user-feedback/) to collect feedback in your frontend from users about their experience with your application. + +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), 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](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). + +### Troubleshooting + +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). + +### Getting Help + +If you encounter issues not covered in the troubleshooting guides: + +1. Visit the [Medusa GitHub repository](https://github.com/medusajs/medusa) to report issues or ask questions. +2. Join the [Medusa Discord community](https://discord.gg/medusajs) for real-time support from community members. +3. Contact the [sales team](https://medusajs.com/contact/) to get help from the Medusa team. + + # Integrate Medusa with ShipStation (Fulfillment) In this guide, you'll learn how to integrate Medusa with ShipStation. @@ -64820,6 +65192,22 @@ Learn how to integrate a third-party fulfillment provider in the [Create Fulfill *** +## Instrumentation + +Integrate a third-party service to monitor performance, errors, and other metrics in your Medusa application. + +- [Sentry](https://docs.medusajs.com/integrations/guides/sentry/index.html.md) + +*** + +## Migration + +Migrate data from another ecommerce platform to Medusa. + +- [Magento](https://docs.medusajs.com/integrations/guides/magento/index.html.md) + +*** + ## Notification A Notification Module Provider sends messages to users and customers in your Medusa application using a third-party service. diff --git a/www/apps/book/sidebar.mjs b/www/apps/book/sidebar.mjs index 808f889220..198b48e481 100644 --- a/www/apps/book/sidebar.mjs +++ b/www/apps/book/sidebar.mjs @@ -593,6 +593,13 @@ export const sidebars = [ type: "link", path: "/learn/debugging-and-testing/instrumentation", title: "Instrumentation", + children: [ + { + type: "ref", + path: "/resources/integrations/guides/sentry", + title: "Guide: Sentry", + }, + ], }, { type: "link", diff --git a/www/apps/resources/app/integrations/guides/algolia/page.mdx b/www/apps/resources/app/integrations/guides/algolia/page.mdx index 0910643f02..655dd889c4 100644 --- a/www/apps/resources/app/integrations/guides/algolia/page.mdx +++ b/www/apps/resources/app/integrations/guides/algolia/page.mdx @@ -692,7 +692,7 @@ export async function POST( } ``` -Since you export a `POST` route handler function, you expose an `API` route at `/admin/algolia/sync`. The route handler function accepts two parameters: +Since you export a `POST` route handler function, you expose a `POST` API route at `/admin/algolia/sync`. The route handler function accepts two parameters: 1. A request object with details and context on the request, such as body parameters or authenticated user details. 2. A response object to manipulate and send the response. diff --git a/www/apps/resources/app/integrations/guides/sentry/page.mdx b/www/apps/resources/app/integrations/guides/sentry/page.mdx new file mode 100644 index 0000000000..b3897dd9b6 --- /dev/null +++ b/www/apps/resources/app/integrations/guides/sentry/page.mdx @@ -0,0 +1,405 @@ +import { Card, Prerequisites, Details, WorkflowDiagram } from "docs-ui" +import { Github, PlaySolid } from "@medusajs/icons" + +export const metadata = { + title: `Integrate Sentry (Instrumentation) with Medusa`, +} + +# {metadata.title} + +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](https://sentry.io/). 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. + +## Summary + +By following this tutorial, you'll learn how to: + +- Install and set up Medusa. +- Set up instrumentation with Sentry. You'll trace HTTP requests, workflows, Query usages, and database operations. +- Capture HTTP request errors in Sentry. +- Test monitoring and error tracking. + +You can follow this tutorial whether you're new to Medusa or an advanced Medusa developer. + +![Diagram showcasing what is traced in Sentry](https://res.cloudinary.com/dza7lstvk/image/upload/v1750069550/Medusa%20Resources/sentry-integration_xb2ior.jpg) + + + +--- + +## Step 1: Install a Medusa Application + + + +Start by installing the Medusa application on your machine with the following command: + +```bash +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](../../../nextjs-starter/page.mdx), choose "Yes." + +Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. + + + +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](!docs!/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](!docs!/learn/introduction/architecture). + + + +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. + + + +Check out the [troubleshooting guides](../../../troubleshooting/create-medusa-app-errors/page.mdx) for help. + + + +--- + +## Step 2: Set Up Instrumentation with Sentry + +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. + + + +Refer to the [Instrumentation](!docs!/learn/debugging-and-testing/instrumentation) documentation for more details on how to set up instrumentation in Medusa. + + + +### a. Install Instrumentation Dependencies + +To set up instrumentation in Medusa, you need to install the necessary OpenTelemetry dependencies. + +In your Medusa application's directory, run the following command: + +```bash npm2yarn +npm install @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/sdk-trace-node @opentelemetry/instrumentation-pg +``` + +Then, 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: + +```bash npm2yarn +npm install @sentry/node @opentelemetry/api @opentelemetry/exporter-trace-otlp-grpc @sentry/opentelemetry-node +``` + +### b. Configure Instrumentation + +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: + +```ts title="instrumentation.ts" +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](https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_sdk-node.NodeSDKConfiguration.html) 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. + +### c. Set Up a Sentry Project + +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: + +1. [Log in or sign up](https://sentry.io/signup/) to Sentry. +2. In your Sentry dashboard, if you're new to Sentry, click the "Start" button. Otherwise, go to Projects from the sidebar and click the "Create Project" button. +3. In the "Select Platform" step, select "Node.js" as the platform, then select "Node, Vanilla" in the pop-up. + +![Screenshot of the pop up with Node, Vanilla selected](https://res.cloudinary.com/dza7lstvk/image/upload/v1750064385/Medusa%20Resources/CleanShot_2025-06-16_at_10.29.29_2x_dkmwtn.png) + +4. In the "Configure Node.js SDK" step, you can find your DSN in the second code block. Copy the DSN, as you'll need it in the next step. + +![Screenshot of the Configure Node.js SDK step with the DSN highlighted](https://res.cloudinary.com/dza7lstvk/image/upload/v1750064502/Medusa%20Resources/CleanShot_2025-06-16_at_12.00.36_2x_wlc0o1.png) + +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: + +```shell title=".env" +SENTRY_DSN=your_sentry_dsn_here +``` + +Replace `your_sentry_dsn_here` with the DSN you copied from Sentry. + +### Test Tracing in 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 Medusa application's directory: + +```bash npm2yarn +npm run dev +``` + +You'll find in the terminal the following message: + +```bash +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: + +1. In your Sentry dashboard, go to Explore → Traces from the sidebar. +2. You'll find a list of traces on this page, including HTTP requests made to log in to the Medusa Admin dashboard. + +![Sentry dashboard with traces listed](https://res.cloudinary.com/dza7lstvk/image/upload/v1750065824/Medusa%20Resources/CleanShot_2025-06-16_at_12.23.29_2x_at87kq.png) + +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. + +![Sentry trace details with HTTP request and workflow execution](https://res.cloudinary.com/dza7lstvk/image/upload/v1750065922/Medusa%20Resources/CleanShot_2025-06-16_at_12.25.10_2x_w8jzgl.png) + +### Test Tracing for Customizations + +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. + + + +An [API Route](!docs!/learn/fundamentals/api-routes) is an endpoint that exposes commerce features to external applications and clients, such as storefronts. + + + +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: + +```ts title="src/api/test-sentry/route.ts" +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: + +1. A request object with details and context on the request, such as body parameters. +2. A response object to manipulate and send the response. + +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`: + +```bash +curl http://localhost:9000/test-sentry +``` + +You'll receive the following error in the response: + +```json +{ + "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. + + + +![Trace dashboard with the test API route trace](https://res.cloudinary.com/dza7lstvk/image/upload/v1750066376/Medusa%20Resources/CleanShot_2025-06-16_at_12.32.37_2x_uox6r1.png) + +If you click on the Trace ID, you'll see the details of the trace. + +![Sentry trace details with error breadcrumbs](https://res.cloudinary.com/dza7lstvk/image/upload/v1750066493/Medusa%20Resources/CleanShot_2025-06-16_at_12.34.33_2x_unzktq.png) + +--- + +## Step 3: Capture HTTP Request Errors in Sentry + +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. + + + +Refer to the [Throwing and Handling Errors](!docs!/learn/fundamentals/api-routes/errors) guide to learn more about Medusa's default error handling behavior. + + + +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."], +] + +```ts title="src/api/middlewares.ts" highlights={errorHandlerHighlights} +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. + +### Test Error Capturing in Sentry + +To test out error capturing in Sentry, start the Medusa application if it's not already running: + +```bash npm2yarn +npm run dev +``` + +Then, send a `GET` request to the `/test-sentry` API route you created earlier: + +```bash +curl http://localhost:9000/test-sentry +``` + +You'll receive the same error response as before: + +```json +{ + "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. + +![Sentry trace details with error message](https://res.cloudinary.com/dza7lstvk/image/upload/v1750347022/Medusa%20Resources/CleanShot_2025-06-19_at_18.29.57_2x_aenvrd.png) + +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. + +![Error details in Sentry](https://res.cloudinary.com/dza7lstvk/image/upload/v1750347022/Medusa%20Resources/CleanShot_2025-06-19_at_18.30.07_2x_oz5y9e.png) + +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. + +--- + +## Next Steps + +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: + +- [Alerts](https://docs.sentry.io/product/alerts/) to get notified about critical issues in your application. You can receive alerts via email, Slack, or other channels. +- [Profiling](https://docs.sentry.io/platforms/javascript/guides/nextjs/profiling/node/) to analyze your application's performance and identify bottlenecks. +- [User feedback](https://docs.sentry.io/product/user-feedback/) to collect feedback in your frontend from users about their experience with your application. + +If you're new to Medusa, check out the [main documentation](!docs!/learn), 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](../../../commerce-modules/page.mdx). + +### Troubleshooting + +If you encounter issues during your development, check out the [troubleshooting guides](../../../troubleshooting/page.mdx). + +### Getting Help + +If you encounter issues not covered in the troubleshooting guides: + +1. Visit the [Medusa GitHub repository](https://github.com/medusajs/medusa) to report issues or ask questions. +2. Join the [Medusa Discord community](https://discord.gg/medusajs) for real-time support from community members. +3. Contact the [sales team](https://medusajs.com/contact/) to get help from the Medusa team. diff --git a/www/apps/resources/app/integrations/page.mdx b/www/apps/resources/app/integrations/page.mdx index 4a621206ab..ec76a0a288 100644 --- a/www/apps/resources/app/integrations/page.mdx +++ b/www/apps/resources/app/integrations/page.mdx @@ -158,6 +158,46 @@ Learn how to integrate a third-party fulfillment provider in the [Create Fulfill --- +## Instrumentation + +Integrate a third-party service to monitor performance, errors, and other metrics in your Medusa application. + + + +--- + +## Migration + +Migrate data from another ecommerce platform to Medusa. + + + +--- + ## Notification A Notification Module Provider sends messages to users and customers in your Medusa application using a third-party service. diff --git a/www/apps/resources/app/recipes/bundled-products/examples/standard/page.mdx b/www/apps/resources/app/recipes/bundled-products/examples/standard/page.mdx index d823faa01f..f0bd702b0e 100644 --- a/www/apps/resources/app/recipes/bundled-products/examples/standard/page.mdx +++ b/www/apps/resources/app/recipes/bundled-products/examples/standard/page.mdx @@ -1277,7 +1277,7 @@ const CreateBundledProduct = () => { ]) // TODO fetch products } -export default CreateBundledProduct; +export default CreateBundledProduct ``` You create a `CreateBundledProduct` component that defines the following state variables: diff --git a/www/apps/resources/generated/edit-dates.mjs b/www/apps/resources/generated/edit-dates.mjs index ba17905c62..1d572d3e5b 100644 --- a/www/apps/resources/generated/edit-dates.mjs +++ b/www/apps/resources/generated/edit-dates.mjs @@ -103,7 +103,7 @@ export const generatedEditDates = { "app/deployment/admin/vercel/page.mdx": "2024-10-16T08:10:29.377Z", "app/deployment/medusa-application/railway/page.mdx": "2025-04-17T08:28:58.981Z", "app/deployment/storefront/vercel/page.mdx": "2025-05-20T07:51:40.712Z", - "app/deployment/page.mdx": "2025-06-20T08:36:52.947Z", + "app/deployment/page.mdx": "2025-06-24T08:50:10.114Z", "app/integrations/page.mdx": "2025-05-26T14:47:43.842Z", "app/medusa-cli/page.mdx": "2024-08-28T11:25:32.382Z", "app/medusa-container-resources/page.mdx": "2025-04-17T08:48:10.255Z", @@ -113,7 +113,7 @@ export const generatedEditDates = { "app/recipes/commerce-automation/page.mdx": "2025-05-20T07:51:40.719Z", "app/recipes/digital-products/examples/standard/page.mdx": "2025-04-24T15:41:05.364Z", "app/recipes/digital-products/page.mdx": "2025-05-20T07:51:40.719Z", - "app/recipes/ecommerce/page.mdx": "2025-06-20T08:37:23.051Z", + "app/recipes/ecommerce/page.mdx": "2025-06-24T08:50:10.116Z", "app/recipes/marketplace/examples/vendors/page.mdx": "2025-05-20T07:51:40.721Z", "app/recipes/marketplace/page.mdx": "2025-05-20T07:51:40.721Z", "app/recipes/multi-region-store/page.mdx": "2025-05-20T07:51:40.721Z", @@ -195,16 +195,16 @@ export const generatedEditDates = { "app/commerce-modules/api-key/page.mdx": "2025-04-17T08:48:16.605Z", "app/commerce-modules/auth/create-actor-type/page.mdx": "2025-05-20T07:51:40.707Z", "app/infrastructure-modules/page.mdx": "2025-05-21T13:01:59.821Z", - "app/infrastructure-modules/workflow-engine/redis/page.mdx": "2025-06-20T08:34:21.977Z", + "app/infrastructure-modules/workflow-engine/redis/page.mdx": "2025-06-24T08:50:10.115Z", "app/infrastructure-modules/notification/sendgrid/page.mdx": "2025-05-20T07:51:40.715Z", "app/commerce-modules/api-key/concepts/page.mdx": "2024-10-07T13:59:37.529Z", "app/infrastructure-modules/workflow-engine/page.mdx": "2025-04-17T08:29:00.881Z", "app/infrastructure-modules/cache/page.mdx": "2025-04-17T08:29:00.741Z", - "app/infrastructure-modules/file/s3/page.mdx": "2025-06-20T08:38:24.029Z", + "app/infrastructure-modules/file/s3/page.mdx": "2025-06-24T08:50:10.115Z", "app/commerce-modules/api-key/_events/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/api-key/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00", - "app/infrastructure-modules/cache/redis/page.mdx": "2025-06-20T08:33:53.038Z", - "app/infrastructure-modules/event/redis/page.mdx": "2025-06-20T08:34:03.057Z", + "app/infrastructure-modules/cache/redis/page.mdx": "2025-06-24T08:50:10.115Z", + "app/infrastructure-modules/event/redis/page.mdx": "2025-06-24T08:50:10.115Z", "app/infrastructure-modules/event/local/page.mdx": "2025-03-27T14:53:13.309Z", "app/infrastructure-modules/workflow-engine/in-memory/page.mdx": "2024-11-19T16:37:47.262Z", "app/infrastructure-modules/cache/in-memory/page.mdx": "2024-11-19T16:37:47.261Z", @@ -6022,7 +6022,7 @@ export const generatedEditDates = { "app/references-overview/page.mdx": "2025-03-10T12:55:49.803Z", "app/infrastructure-modules/locking/page.mdx": "2025-04-17T08:29:00.564Z", "app/infrastructure-modules/locking/postgres/page.mdx": "2025-03-27T14:53:13.310Z", - "app/infrastructure-modules/locking/redis/page.mdx": "2025-06-20T08:34:12.702Z", + "app/infrastructure-modules/locking/redis/page.mdx": "2025-06-24T08:50:10.115Z", "references/locking/interfaces/locking.ILockingModule/page.mdx": "2025-05-20T07:51:40.955Z", "references/locking/interfaces/locking.ILockingProvider/page.mdx": "2025-05-20T07:51:40.955Z", "references/modules/locking/page.mdx": "2025-03-12T12:28:30.419Z", @@ -6048,10 +6048,10 @@ export const generatedEditDates = { "app/troubleshooting/workflow-errors/step-x-defined/page.mdx": "2025-03-21T07:09:02.741Z", "app/troubleshooting/workflow-errors/when-then/page.mdx": "2025-03-21T08:35:45.145Z", "app/how-to-tutorials/tutorials/abandoned-cart/page.mdx": "2025-05-20T07:51:40.713Z", - "app/integrations/guides/algolia/page.mdx": "2025-05-20T07:51:40.715Z", + "app/integrations/guides/algolia/page.mdx": "2025-06-16T09:29:42.556Z", "app/integrations/guides/magento/page.mdx": "2025-05-20T07:51:40.716Z", "app/js-sdk/auth/overview/page.mdx": "2025-03-28T08:05:32.622Z", - "app/how-to-tutorials/tutorials/loyalty-points/page.mdx": "2025-06-20T08:35:30.861Z", + "app/how-to-tutorials/tutorials/loyalty-points/page.mdx": "2025-06-24T08:50:10.114Z", "references/js_sdk/admin/Admin/properties/js_sdk.admin.Admin.plugin/page.mdx": "2025-04-11T09:04:55.084Z", "references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.createAddress/page.mdx": "2025-05-20T07:51:40.936Z", "references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.deleteAddress/page.mdx": "2025-04-11T09:04:54.015Z", @@ -6545,5 +6545,6 @@ export const generatedEditDates = { "references/utils/Payment/variables/utils.Payment.PaymentEvents/page.mdx": "2025-06-05T19:05:53.491Z", "references/utils/types/utils.NormalizedRow/page.mdx": "2025-06-05T19:05:53.365Z", "references/utils/utils.Payment/page.mdx": "2025-06-05T19:05:53.489Z", - "app/integrations/guides/slack/page.mdx": "2025-06-03T09:37:42.528Z" + "app/integrations/guides/slack/page.mdx": "2025-06-03T09:37:42.528Z", + "app/integrations/guides/sentry/page.mdx": "2025-06-16T10:11:29.955Z" } \ No newline at end of file diff --git a/www/apps/resources/generated/files-map.mjs b/www/apps/resources/generated/files-map.mjs index ef35e12656..0b0f26d0f8 100644 --- a/www/apps/resources/generated/files-map.mjs +++ b/www/apps/resources/generated/files-map.mjs @@ -887,6 +887,10 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/integrations/guides/segment/page.mdx", "pathname": "/integrations/guides/segment" }, + { + "filePath": "/www/apps/resources/app/integrations/guides/sentry/page.mdx", + "pathname": "/integrations/guides/sentry" + }, { "filePath": "/www/apps/resources/app/integrations/guides/shipstation/page.mdx", "pathname": "/integrations/guides/shipstation" diff --git a/www/apps/resources/generated/generated-integrations-sidebar.mjs b/www/apps/resources/generated/generated-integrations-sidebar.mjs index 4209009517..917e4866c1 100644 --- a/www/apps/resources/generated/generated-integrations-sidebar.mjs +++ b/www/apps/resources/generated/generated-integrations-sidebar.mjs @@ -139,6 +139,23 @@ const generatedgeneratedIntegrationsSidebarSidebar = { } ] }, + { + "loaded": true, + "isPathHref": true, + "type": "category", + "title": "Instrumentation", + "initialOpen": true, + "children": [ + { + "loaded": true, + "isPathHref": true, + "type": "link", + "path": "/integrations/guides/sentry", + "title": "Sentry", + "children": [] + } + ] + }, { "loaded": true, "isPathHref": true, diff --git a/www/apps/resources/sidebars/integrations.mjs b/www/apps/resources/sidebars/integrations.mjs index 301c91fbb8..7530402055 100644 --- a/www/apps/resources/sidebars/integrations.mjs +++ b/www/apps/resources/sidebars/integrations.mjs @@ -95,6 +95,18 @@ export const integrationsSidebar = [ }, ], }, + { + type: "category", + title: "Instrumentation", + initialOpen: true, + children: [ + { + type: "link", + path: "/integrations/guides/sentry", + title: "Sentry", + }, + ], + }, { type: "category", title: "Migration",