diff --git a/docs/concepts/otlp/sentry-with-otel.mdx b/docs/concepts/otlp/sentry-with-otel.mdx index 7553d9655aeb2..4e07fd25d68fb 100644 --- a/docs/concepts/otlp/sentry-with-otel.mdx +++ b/docs/concepts/otlp/sentry-with-otel.mdx @@ -87,7 +87,7 @@ If you're running both a Sentry SDK and OTel instrumentation in the same backend - - + +_Import name: `Sentry.openTelemetryIntegration`_ + +This integration is not enabled by default. Use it when OpenTelemetry owns tracing in your application and you want Sentry's errors, logs, metrics and check-ins to land on the same traces. + +Everything Sentry sends that carries trace information is attached to the OpenTelemetry span that's active when it happens, so it shows up on the same trace as the spans your OpenTelemetry SDK exports. Outgoing request propagation is left to your OpenTelemetry propagator. + +An active Sentry span still takes precedence, so this only changes what happens when Sentry has no span of its own. + + + +This integration sends no spans. To get your OpenTelemetry spans into Sentry, point your own exporter at Sentry's OTLP endpoint with `getOtlpTracesEndpoint()`, as shown below. + + + +## Install + +Install the OpenTelemetry packages you need alongside the Sentry SDK: + +```bash {tabTitle:npm} +npm install @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http +``` + +```bash {tabTitle:yarn} +yarn add @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http +``` + +```bash {tabTitle:pnpm} +pnpm add @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http +``` + +## Configure + +Leave Sentry tracing off so the two pipelines stay separate. `getOtlpTracesEndpoint()` turns your DSN into the URL and auth headers of Sentry's OTLP endpoint: + +```javascript +import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; +import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base"; +import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node"; +import * as Sentry from "@sentry/node"; + +const provider = new NodeTracerProvider({ + spanProcessors: [ + new BatchSpanProcessor( + new OTLPTraceExporter(Sentry.getOtlpTracesEndpoint("___PUBLIC_DSN___")) + ), + ], +}); + +provider.register(); + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // Leave the OpenTelemetry setup to your own provider + enableOpenTelemetrySetup: false, + // No `tracesSampleRate`: OpenTelemetry owns spans, Sentry owns errors and logs + integrations: [Sentry.openTelemetryIntegration()], +}); +``` + +Sentry sends no spans with this setup, and no Sentry span reaches your OpenTelemetry pipeline. + +If you'd rather have Sentry own tracing and add your own instrumentation on top, see Using Your Existing OpenTelemetry Setup instead. diff --git a/docs/platforms/javascript/common/install/index.mdx b/docs/platforms/javascript/common/install/index.mdx index 890fe54413bc7..c171573bed1ec 100644 --- a/docs/platforms/javascript/common/install/index.mdx +++ b/docs/platforms/javascript/common/install/index.mdx @@ -57,10 +57,6 @@ If you are using `import` in your application, your installation method depends If you do not compile your code, you'll need to follow the [ESM instructions](./esm). -### I don't need automatic spans/transactions - -If you don't need spans emitted by OpenTelemetry instrumentation, you can use `@sentry/node-core` in [Lightweight Mode](./lightweight) without OpenTelemetry dependencies. You still get errors, logs, metrics, breadcrumbs, and more. This mode is experimental. - diff --git a/docs/platforms/javascript/common/install/lightweight.mdx b/docs/platforms/javascript/common/install/lightweight.mdx deleted file mode 100644 index dd87680c2cc5b..0000000000000 --- a/docs/platforms/javascript/common/install/lightweight.mdx +++ /dev/null @@ -1,211 +0,0 @@ ---- -title: Lightweight Mode -sidebar_order: 15 -description: "Learn about running Sentry in lightweight mode without OpenTelemetry, or with optional OTLP integration for existing OTel setups." -supported: - - javascript.node - - javascript.connect - - javascript.express - - javascript.fastify - - javascript.hapi - - javascript.hono - - javascript.koa ---- - - - Lightweight mode is experimental and may have breaking changes in minor or - patch releases. - - - - Are you unsure if you should use this installation method? Review our - [installation methods](../). - - -If you don't need automatic spans/transactions, you can use `@sentry/node-core/light` which doesn't require OpenTelemetry dependencies. This mode is ideal when: - -- You only need error tracking, logs, or metrics without tracing data (no automatic span creation) -- You want to minimize bundle size and runtime overhead -- You don't need spans emitted by OpenTelemetry instrumentation - -You still get error tracking, logs, metrics, breadcrumbs, context/user data, local variables capture, distributed tracing (via `sentry-trace` and `baggage` headers), and automatic request isolation (Node.js 22+). - -If needed, you can still manually create spans by using Sentry's custom instrumentation APIs like `startSpan`. - -If you already have your own OpenTelemetry setup, you can also use the [OTLP integration](#using-with-opentelemetry-otlp) to link Sentry errors to your OTel traces and export spans to Sentry. - -## Prerequisites - -- **Node.js 22.12.0+** is recommended for full functionality (automatic request isolation) -- Lower Node.js versions work but with limited capabilities (see [Request Isolation](#request-isolation) below) - -## Step 1: Install - -```bash {tabTitle:npm} -npm install @sentry/node-core --save -``` - -```bash {tabTitle:yarn} -yarn add @sentry/node-core -``` - -```bash {tabTitle:pnpm} -pnpm add @sentry/node-core -``` - -## Step 2: Configure - -Import from `@sentry/node-core/light` and call `Sentry.init()` as early as possible in your application lifecycle: - -```javascript {tabTitle:ESM} -import * as Sentry from "@sentry/node-core/light"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", -}); - -// Now create your HTTP server or framework app -``` - -```javascript {tabTitle:CJS} -const Sentry = require("@sentry/node-core/light"); - -Sentry.init({ - dsn: "___PUBLIC_DSN___", -}); - -// Now create your HTTP server or framework app -``` - -## Step 3: Verify - -To verify that Sentry is working, capture a test error: - -```javascript -Sentry.captureException(new Error("Sentry lightweight mode test")); -``` - -After running your application, you should see this error appear in your [Sentry dashboard](https://sentry.io). - -## Request Isolation - -Request isolation ensures that errors, breadcrumbs, and context are correctly scoped to individual requests. - -### Node.js 22.12.0+ - -Request isolation works automatically. No additional setup is needed — just make sure `Sentry.init()` is called before you create your HTTP server. - -### Node.js < 22 - -You need to manually wrap your request handler with `Sentry.withIsolationScope()`: - -```javascript -import * as Sentry from "@sentry/node-core/light"; -import http from "http"; - -const server = http.createServer((req, res) => { - Sentry.withIsolationScope(() => { - // Your request handling code - Sentry.setUser({ id: "user-id" }); - res.end("OK"); - }); -}); -``` - - - When using manual isolation on Node.js < 22, distributed tracing will not - work correctly. - - -## Conversation IDs - -To group AI spans in [Conversations](/product/agents/conversations/), add -`conversationIdIntegration` and call `setConversationId`. Neither is included in -lightweight mode by default: - -```javascript -import * as Sentry from "@sentry/node-core/light"; -import { conversationIdIntegration, setConversationId } from "@sentry/core"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - integrations: [ - ...Sentry.getDefaultIntegrations(), - conversationIdIntegration(), - ], -}); - -setConversationId("conv_abc123"); -``` - -## When to Use Lightweight Mode vs `@sentry/node` - -| | `@sentry/node` | `@sentry/node-core/light` | -| ------------------------------- | ------------------- | ---------------------------------------------- | -| **Error tracking** | Yes | Yes | -| **Logs and metrics** | Yes | Yes | -| **Automatic spans** | Yes | No | -| **OpenTelemetry auto-included** | Yes | No | -| **Dependency footprint** | Larger | Minimal | -| **Best for** | Full observability | No auto-instrumentation, manual tracing setup | - -If you need automatic spans for HTTP requests, database queries, and other operations, use `@sentry/node` (the default). If you don't need automatically created spans and want minimal dependencies, use lightweight mode. - -## Using with OpenTelemetry (OTLP) - - - -If you already have your own OpenTelemetry setup and want to bridge it with Sentry, you can use the `otlpIntegration` from `@sentry/node-core/light/otlp`. This integration: - -- Links Sentry errors and logs to the active OpenTelemetry trace context -- Exports OpenTelemetry spans to Sentry via [OTLP](/concepts/otlp/) - -### Install OpenTelemetry Dependencies - -In addition to `@sentry/node-core`, install the OpenTelemetry packages you need: - -```bash {tabTitle:npm} -npm install @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http -``` - -```bash {tabTitle:yarn} -yarn add @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http -``` - -```bash {tabTitle:pnpm} -pnpm add @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http -``` - -### Configure - -Set up your OpenTelemetry `TracerProvider` first, then initialize Sentry with the `otlpIntegration`: - -```javascript -import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node"; -import * as Sentry from "@sentry/node-core/light"; -import { otlpIntegration } from "@sentry/node-core/light/otlp"; - -// Set up your OpenTelemetry TracerProvider as usual -const provider = new NodeTracerProvider(); -provider.register(); - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - integrations: [otlpIntegration()], -}); -``` - -The integration automatically derives the OTLP endpoint from your DSN. To send traces to your own collector instead, pass a `collectorUrl`: - -```javascript -otlpIntegration({ - collectorUrl: "https://my-collector.example.com/v1/traces", -}); -``` - -### Options - -| Option | Type | Default | Description | -|---|---|---|---| -| `setupOtlpTracesExporter` | `boolean` | `true` | Automatically configure an exporter to send OTLP traces to the right project from the DSN or `collectorUrl`. Set to `false` to set up the `TracerProvider` manually. | -| `collectorUrl` | `string` | `undefined` | URL of your own OpenTelemetry collector. When set, traces are sent here instead of the Sentry OTLP endpoint derived from the DSN. | diff --git a/docs/platforms/javascript/common/opentelemetry/custom-setup.mdx b/docs/platforms/javascript/common/opentelemetry/custom-setup.mdx index a294374981683..a77f7d8cf5d71 100644 --- a/docs/platforms/javascript/common/opentelemetry/custom-setup.mdx +++ b/docs/platforms/javascript/common/opentelemetry/custom-setup.mdx @@ -29,164 +29,43 @@ notSupported: sidebar_order: 0 --- - - -Use this guide when you already have a completely custom OpenTelemetry setup or when you intend to add a custom OpenTelemetry setup next to the Sentry SDK. - -Setting `skipOpenTelemetrySetup: true` disables the Sentry SDK's automatic OpenTelemetry configuration, **requiring** you to perform the setup manually. For example, to ensure errors are correctly associated with their scope, you must add the `SentryContextManager` to your OpenTelemetry setup. You can find details on the required manual setup further down on this page. - -If you are looking to simply add individual OpenTelemetry instrumentation to your Sentry setup, you should read Adding Additional OpenTelemetry Instrumentation instead. - - - - - - -If you don't need the full `@sentry/node` SDK and want a simpler way to bridge your existing OpenTelemetry setup with Sentry, consider using lightweight mode with the OTLP integration instead. It requires significantly less manual wiring. - - - +Sentry and OpenTelemetry are separate pipelines. The SDK doesn't register an OpenTelemetry tracer provider by default, and it no longer routes spans from a provider you own into Sentry as Sentry spans. - - -## Using Sentry for Error Monitoring Only - -If you have a custom OpenTelemetry setup and only want to use Sentry for error monitoring, you can skip adding the `SentrySpanProcessor`. You'll still need to add the `SentryContextManager`, `SentryPropagator`, and `SentrySampler` to your setup even if you don't want to send any tracing data to Sentry. Read on to learn why this is needed. - -In order for the Sentry SDK to work as expected, and for it to be in sync with OpenTelemetry, we need a few components to be in place. - -**Components needed for Sentry to work correctly:** - -- **SentryContextManager**: Ensures that the OpenTelemetry context is in sync with Sentry, for example to correctly isolate data between simultaneous requests. -- **SentrySampler**: Ensures that the Sentry `tracesSampleRate` is respected. Even if you don't use Sentry for tracing, you'll still need this in order for trace propagation to work as expected. Read [Using a Custom Sampler](./#using-a-custom-sampler) if you want to use a custom sampler. -- **SentryPropagator**: Ensures that trace propagation works correctly. -- [Required Instrumentation](./#required-instrumentation): Ensures that trace propagation works correctly. - -**Additional components needed to also use Sentry for tracing:** - -- **SentrySpanProcessor**: Ensures that spans are correctly sent to Sentry. - - - Trace propagation is needed for Sentry to automatically connect services - together. (For example, if you want to connect the frontend and backend, or - different backend services.) This makes it possible to see related errors - across services.{" "} - - Learn more about Trace Propagation. - - +That leaves two setups, depending on which side owns tracing. -The following code snippet shows how to set up Sentry for error monitoring only: +## OpenTelemetry Owns Tracing - +Keep your own tracer provider and add `openTelemetryIntegration`. Sentry's errors, logs, metrics and check-ins attach to the OpenTelemetry span that's active when they happen, so they land on your traces. -## Required Instrumentation - -By default, Sentry will register OpenTelemetry instrumentation to automatically capture spans for traces spanning incoming and outgoing HTTP requests, DB queries, and more. - -If tracing is not enabled (no `tracesSampleRate` is defined in the SDK configuration), only a minimal amount of OpenTelemetry instrumentation will be registered. This includes the following: - -{/* prettier-ignore-start */} - -- A Sentry-specific HTTP instrumentation that handles request isolation and trace propagation. This can work in parallel with [@opentelemetry/instrumentation-http](https://www.npmjs.com/package/@opentelemetry/instrumentation-http), if you register it. -- [nativeNodeFetchIntegration](/platforms/javascript/guides/node/configuration/integrations/nodefetch/) registers [opentelemetry-instrumentation-fetch-node](https://www.npmjs.com/package/opentelemetry-instrumentation-fetch-node) which is needed for trace propagation. - -{/* prettier-ignore-end */} - - - - If tracing is not enabled, performance instrumentations will not be - registered but they will still be included in the bundle. If you want to - reduce the bundle size or used dependencies, you can also{" "} - - Set up Sentry without Performance Integrations - - - - -These are needed to make sure that trace propagation works correctly. - -If you want to add your own http/node-fetch instrumentation, you have to follow the following steps: - -### Custom HTTP Instrumentation - - - -You can add your own `@opentelemetry/instrumentation-http` instance in your OpenTelemetry setup. However, in this case, you need to disable span creation in Sentry's `httpIntegration`. You can also set `tracePropagation: false` to prevent Sentry from injecting trace headers, letting your OpenTelemetry setup handle propagation instead: - - - ```javascript - const sentryClient = Sentry.init({ - dsn: "___DSN___", - skipOpenTelemetrySetup: true, - integrations: [Sentry.httpIntegration({ spans: false, tracePropagation: false })], -}); - ``` - - - ```javascript - const sentryClient = Sentry.init({ - dsn: "___DSN___", - skipOpenTelemetrySetup: true, - integrations: (integrations) => - // Also filter out the BunServer integration to avoid emitting duplicated spans from Sentry AND your custom OTel instrumentation - integrations.filter((i) => i.name !== "BunServer") +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // No `tracesSampleRate`: OpenTelemetry owns spans + enableOpenTelemetrySetup: false, + integrations: [Sentry.openTelemetryIntegration()], }); ``` - - -It's important that `httpIntegration` is still registered this way to ensure that the Sentry SDK can correctly isolate requests, for example when capturing errors. -### Custom Node Fetch Instrumentation +Sentry emits no spans in this setup. To get your OpenTelemetry spans into Sentry, point your own exporter at Sentry's OTLP endpoint with `getOtlpTracesEndpoint()`, which that page shows in full. -If tracing is disabled, the Node Fetch instrumentation will not emit any spans. In this scenario, it will only inject sentry-specific trace propagation headers. You are free to add your own Node Fetch instrumentation on top of this which may emit spans as you like. +## Sentry Owns Tracing -If your OpenTelemetry setup already handles trace propagation for fetch requests, you can set `tracePropagation: false` to prevent Sentry from injecting duplicate trace headers: +Set `enableOpenTelemetrySetup: true` and the SDK registers its own tracer provider and propagator. Spans created through `@opentelemetry/api` become Sentry spans, alongside the spans the SDK creates itself: ```javascript -const sentryClient = Sentry.init({ - dsn: "___DSN___", - skipOpenTelemetrySetup: true, - integrations: [ - Sentry.nativeNodeFetchIntegration({ tracePropagation: false }), - ], +Sentry.init({ + dsn: "___PUBLIC_DSN___", + tracesSampleRate: 1.0, + enableOpenTelemetrySetup: true, }); ``` -## Using a Custom Sampler +This is already the default on `@sentry/nextjs` and `@sentry/sveltekit`, which need it to capture the spans those frameworks emit. -While you can use your own sampler, we recommend that you use the `SentrySampler`. This will ensure that the correct subset of traces will be sent to Sentry, based on your `tracesSampleRate`. It will also ensure that all other Sentry features like trace propagation work as expected. If you do need to use your own sampler, make sure to wrap your `SamplingResult` with our `wrapSamplingDecision` method like in the example below: +For working with the OpenTelemetry APIs in this setup, see Using OpenTelemetry APIs. - - - - -It is recommended registering your own ESM loader hooks when you have a complete custom OpenTelemetry setup, first and foremost because it makes the most sense architecturally. -You likely went through the effort to set up OpenTelemetry by itself and now you want to add Sentry to your application without messing with your OpenTelemetry setup. - -Additionally, there are a few pitfalls that can very simply be avoided by registering your own hooks: + -- Registering loader hooks multiple times might result in duplicated spans being created. [More details.](https://github.com/getsentry/sentry-javascript/issues/14065#issuecomment-2435546961) -- OpenTelemetry instrumentation in ESM is very sensitive as to _when_ it is added relative to _when_ the loader hooks are registered. - The control over this should stay with the owner of the OpenTelemetry setup and not the Sentry SDK. +`SentryContextManager`, `SentrySampler` and `SentrySpanProcessor` were removed, so wiring Sentry's components into a provider you own is no longer possible. If you were doing that, pick one of the two setups above. - - - - - Learn more about ESM installation methods. - - - diff --git a/docs/platforms/javascript/common/opentelemetry/custom-setup__v10.x.mdx b/docs/platforms/javascript/common/opentelemetry/custom-setup__v10.x.mdx new file mode 100644 index 0000000000000..8e5f273f85b97 --- /dev/null +++ b/docs/platforms/javascript/common/opentelemetry/custom-setup__v10.x.mdx @@ -0,0 +1,191 @@ +--- +title: Using Your Existing OpenTelemetry Setup +description: "Learn how to use your existing custom OpenTelemetry setup with Sentry." +noindex: true # Not indexed because it is a versioned docs page +supported: + - javascript.nextjs + - javascript.node + - javascript.eve + - javascript.aws-lambda + - javascript.azure-functions + - javascript.bun + - javascript.connect + - javascript.express + - javascript.fastify + - javascript.gcp-functions + - javascript.hapi + - javascript.hono + - javascript.koa + - javascript.nestjs + - javascript.nitro + - javascript.nuxt + - javascript.solidstart + - javascript.sveltekit + - javascript.astro + - javascript.remix + - javascript.react-router + - javascript.tanstackstart-react +notSupported: + - javascript +sidebar_order: 0 +--- + + + +Use this guide when you already have a completely custom OpenTelemetry setup or when you intend to add a custom OpenTelemetry setup next to the Sentry SDK. + +Setting `skipOpenTelemetrySetup: true` disables the Sentry SDK's automatic OpenTelemetry configuration, **requiring** you to perform the setup manually. For example, to ensure errors are correctly associated with their scope, you must add the `SentryContextManager` to your OpenTelemetry setup. You can find details on the required manual setup further down on this page. + +If you are looking to simply add individual OpenTelemetry instrumentation to your Sentry setup, you should read Adding Additional OpenTelemetry Instrumentation instead. + + + + + + + + + + + +## Using Sentry for Error Monitoring Only + +If you have a custom OpenTelemetry setup and only want to use Sentry for error monitoring, you can skip adding the `SentrySpanProcessor`. You'll still need to add the `SentryContextManager`, `SentryPropagator`, and `SentrySampler` to your setup even if you don't want to send any tracing data to Sentry. Read on to learn why this is needed. + +In order for the Sentry SDK to work as expected, and for it to be in sync with OpenTelemetry, we need a few components to be in place. + +**Components needed for Sentry to work correctly:** + +- **SentryContextManager**: Ensures that the OpenTelemetry context is in sync with Sentry, for example to correctly isolate data between simultaneous requests. +- **SentrySampler**: Ensures that the Sentry `tracesSampleRate` is respected. Even if you don't use Sentry for tracing, you'll still need this in order for trace propagation to work as expected. Read [Using a Custom Sampler](./#using-a-custom-sampler) if you want to use a custom sampler. +- **SentryPropagator**: Ensures that trace propagation works correctly. +- [Required Instrumentation](./#required-instrumentation): Ensures that trace propagation works correctly. + +**Additional components needed to also use Sentry for tracing:** + +- **SentrySpanProcessor**: Ensures that spans are correctly sent to Sentry. + + + Trace propagation is needed for Sentry to automatically connect services + together. (For example, if you want to connect the frontend and backend, or + different backend services.) This makes it possible to see related errors + across services.{" "} + + Learn more about Trace Propagation. + + + +The following code snippet shows how to set up Sentry for error monitoring only: + + + +## Required Instrumentation + +By default, Sentry will register OpenTelemetry instrumentation to automatically capture spans for traces spanning incoming and outgoing HTTP requests, DB queries, and more. + +If tracing is not enabled (no `tracesSampleRate` is defined in the SDK configuration), only a minimal amount of OpenTelemetry instrumentation will be registered. This includes the following: + +{/* prettier-ignore-start */} + +- A Sentry-specific HTTP instrumentation that handles request isolation and trace propagation. This can work in parallel with [@opentelemetry/instrumentation-http](https://www.npmjs.com/package/@opentelemetry/instrumentation-http), if you register it. +- [nativeNodeFetchIntegration](/platforms/javascript/guides/node/configuration/integrations/nodefetch/) registers [opentelemetry-instrumentation-fetch-node](https://www.npmjs.com/package/opentelemetry-instrumentation-fetch-node) which is needed for trace propagation. + +{/* prettier-ignore-end */} + + + + If tracing is not enabled, performance instrumentations will not be + registered but they will still be included in the bundle. If you want to + reduce the bundle size or used dependencies, you can also{" "} + + Set up Sentry without Performance Integrations + + + + +These are needed to make sure that trace propagation works correctly. + +If you want to add your own http/node-fetch instrumentation, you have to follow the following steps: + +### Custom HTTP Instrumentation + + + +You can add your own `@opentelemetry/instrumentation-http` instance in your OpenTelemetry setup. However, in this case, you need to disable span creation in Sentry's `httpIntegration`. You can also set `tracePropagation: false` to prevent Sentry from injecting trace headers, letting your OpenTelemetry setup handle propagation instead: + + + ```javascript + const sentryClient = Sentry.init({ + dsn: "___DSN___", + skipOpenTelemetrySetup: true, + integrations: [Sentry.httpIntegration({ spans: false, tracePropagation: false })], +}); + ``` + + + +```javascript + const sentryClient = Sentry.init({ + dsn: "___DSN___", + skipOpenTelemetrySetup: true, + integrations: (integrations) => + // Also filter out the BunServer integration to avoid emitting duplicated spans from Sentry AND your custom OTel instrumentation + integrations.filter((i) => i.name !== "BunServer") +}); +``` + + +It's important that `httpIntegration` is still registered this way to ensure that the Sentry SDK can correctly isolate requests, for example when capturing errors. + +### Custom Node Fetch Instrumentation + +If tracing is disabled, the Node Fetch instrumentation will not emit any spans. In this scenario, it will only inject sentry-specific trace propagation headers. You are free to add your own Node Fetch instrumentation on top of this which may emit spans as you like. + +If your OpenTelemetry setup already handles trace propagation for fetch requests, you can set `tracePropagation: false` to prevent Sentry from injecting duplicate trace headers: + +```javascript +const sentryClient = Sentry.init({ + dsn: "___DSN___", + skipOpenTelemetrySetup: true, + integrations: [ + Sentry.nativeNodeFetchIntegration({ tracePropagation: false }), + ], +}); +``` + +## Using a Custom Sampler + +While you can use your own sampler, we recommend that you use the `SentrySampler`. This will ensure that the correct subset of traces will be sent to Sentry, based on your `tracesSampleRate`. It will also ensure that all other Sentry features like trace propagation work as expected. If you do need to use your own sampler, make sure to wrap your `SamplingResult` with our `wrapSamplingDecision` method like in the example below: + + + + + +It is recommended registering your own ESM loader hooks when you have a complete custom OpenTelemetry setup, first and foremost because it makes the most sense architecturally. +You likely went through the effort to set up OpenTelemetry by itself and now you want to add Sentry to your application without messing with your OpenTelemetry setup. + +Additionally, there are a few pitfalls that can very simply be avoided by registering your own hooks: + +- Registering loader hooks multiple times might result in duplicated spans being created. [More details.](https://github.com/getsentry/sentry-javascript/issues/14065#issuecomment-2435546961) +- OpenTelemetry instrumentation in ESM is very sensitive as to _when_ it is added relative to _when_ the loader hooks are registered. + The control over this should stay with the owner of the OpenTelemetry setup and not the Sentry SDK. + + + + + + + Learn more about ESM installation methods. + + + diff --git a/docs/platforms/javascript/common/opentelemetry/index.mdx b/docs/platforms/javascript/common/opentelemetry/index.mdx index 468373c3a6025..41fad1b314b54 100644 --- a/docs/platforms/javascript/common/opentelemetry/index.mdx +++ b/docs/platforms/javascript/common/opentelemetry/index.mdx @@ -31,10 +31,15 @@ notSupported: beta: true --- -The Sentry SDK uses [OpenTelemetry](https://opentelemetry.io/) under the hood. This means that any OpenTelemetry instrumentation that emits spans will automatically be picked up by Sentry without any further configuration. +Sentry and [OpenTelemetry](https://opentelemetry.io/) are separate pipelines, and you choose how they connect. -To start capturing traces and spans, set up Tracing and Performance Monitoring with your Sentry SDK. If you don't use tracing, Sentry still connects to OpenTelemetry under the hood to ensure that context isolation and trace propagation works correctly. +The SDK emits its own spans and isolates scopes on its own, so tracing works without any OpenTelemetry setup. What it doesn't do by default is register an OpenTelemetry tracer provider, so spans created through `@opentelemetry/api` aren't captured. To start capturing traces and spans from the SDK itself, set up Tracing and Performance Monitoring. -By default, Sentry will automatically set up OpenTelemetry for you, but you can also use your own OpenTelemetry setup. Read the guides below to learn how to use a custom OpenTelemetry setup or how to get the most out of the Sentry and OpenTelemetry integration. +There are two ways to connect the two: + +- **OpenTelemetry owns tracing.** Keep your own tracer provider and add `openTelemetryIntegration`, so Sentry's errors, logs, metrics and check-ins land on your OpenTelemetry traces. Export your spans to Sentry over OTLP. +- **Sentry owns tracing.** Set `enableOpenTelemetrySetup: true` and the SDK registers its own tracer provider, so spans created through `@opentelemetry/api` become Sentry spans. This is the default on `@sentry/nextjs` and `@sentry/sveltekit`. + +Read the guides below for either setup. diff --git a/docs/platforms/javascript/common/opentelemetry/index__v10.x.mdx b/docs/platforms/javascript/common/opentelemetry/index__v10.x.mdx new file mode 100644 index 0000000000000..af988e4926e3a --- /dev/null +++ b/docs/platforms/javascript/common/opentelemetry/index__v10.x.mdx @@ -0,0 +1,41 @@ +--- +title: OpenTelemetry Support +description: "Learn how to use OpenTelemetry with Sentry." +noindex: true # Not indexed because it is a versioned docs page +sidebar_order: 14 +sidebar_section: configuration +supported: + - javascript.nextjs + - javascript.node + - javascript.eve + - javascript.aws-lambda + - javascript.azure-functions + - javascript.bun + - javascript.connect + - javascript.express + - javascript.fastify + - javascript.gcp-functions + - javascript.hapi + - javascript.hono + - javascript.koa + - javascript.nestjs + - javascript.nitro + - javascript.nuxt + - javascript.solidstart + - javascript.sveltekit + - javascript.astro + - javascript.remix + - javascript.react-router + - javascript.tanstackstart-react +notSupported: + - javascript +beta: true +--- + +The Sentry SDK uses [OpenTelemetry](https://opentelemetry.io/) under the hood. This means that any OpenTelemetry instrumentation that emits spans will automatically be picked up by Sentry without any further configuration. + +To start capturing traces and spans, set up Tracing and Performance Monitoring with your Sentry SDK. If you don't use tracing, Sentry still connects to OpenTelemetry under the hood to ensure that context isolation and trace propagation works correctly. + +By default, Sentry will automatically set up OpenTelemetry for you, but you can also use your own OpenTelemetry setup. Read the guides below to learn how to use a custom OpenTelemetry setup or how to get the most out of the Sentry and OpenTelemetry integration. + + diff --git a/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis.mdx b/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis.mdx index 8d0aaa5120a4a..b763658e36329 100644 --- a/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis.mdx +++ b/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis.mdx @@ -29,60 +29,17 @@ notSupported: sidebar_order: 1 --- -Sentry supports OpenTelemetry APIs out of the box. Any spans started using OpenTelemetry APIs will be automatically captured by Sentry, while any spans started using the Sentry SDK will be automatically propagated to OpenTelemetry. +These APIs work with either OpenTelemetry setup. What changes is where the spans go. With `enableOpenTelemetrySetup: true`, the SDK registers its own tracer provider, so spans started through OpenTelemetry APIs become Sentry spans and spans started with the Sentry SDK are propagated to OpenTelemetry. With a tracer provider of your own, the spans go to your pipeline and reach Sentry through your OTLP exporter. ## Adding Additional OpenTelemetry Instrumentation -While the Sentry SDK includes some OpenTelemetry instrumentation out of the box, you may want to add additional instrumentation to your application. This can be done by registering the instrumentation through OpenTelemetry like the example below: - -```javascript {tabTitle: ESM} {12-13} -import * as Sentry from "@sentry/node"; -import { - GenericPoolInstrumentation, -} from "@opentelemetry/instrumentation-generic-pool"; - -Sentry.init({ - dsn: "___DSN___", - - // The SentrySampler will use this to determine which traces to sample - tracesSampleRate: 1.0, - - // Add additional OpenTelemetry instrumentation: - openTelemetryInstrumentations: [new GenericPoolInstrumentation()], -}); -``` -```javascript {tabTitle: CJS} {12-13} -const Sentry = require("@sentry/node"); -const { - GenericPoolInstrumentation, -} = require("@opentelemetry/instrumentation-generic-pool"); - -Sentry.init({ - dsn: "___DSN___", - - // The SentrySampler will use this to determine which traces to sample - tracesSampleRate: 1.0, - - // Add additional OpenTelemetry instrumentation: - openTelemetryInstrumentations: [new GenericPoolInstrumentation()], -}); -``` - - - It is possible to add instrumentations via `registerInstrumentations()` from - `@opentelemetry/instrumentation`. However, with ESM (`import`/`export` syntax) - you need to be careful to do so before importing any modules that should be - instrumented. - -As a rule of thumb, `registerInstrumentations()` should be called right after, and in the same context as registering ESM Loaders. - - +Register instrumentation through OpenTelemetry's own `registerInstrumentations()` from `@opentelemetry/instrumentation`. With ESM, call it before importing any module that should be instrumented. ## Using an OpenTelemetry Tracer We recommend using `Sentry.startSpan()` and related APIs to create spans, but you can also create spans using native OpenTelemetry APIs. -You can access the tracer Sentry uses via `client.tracer` and then create spans with OpenTelemetry APIs, as shown below: +You can access the tracer via `client.tracer` and then create spans with OpenTelemetry APIs, as shown below. It reads the globally registered tracer provider, so it gives you Sentry's tracer or your own, depending on the setup: ```javascript {tabTitle: ESM} import * as Sentry from "@sentry/node"; @@ -93,6 +50,7 @@ tracer.startActiveSpan("span name", () => { // measure something }); ``` + ```javascript {tabTitle: CJS} const Sentry = require("@sentry/node"); @@ -103,50 +61,20 @@ tracer.startActiveSpan("span name", () => { }); ``` -You can also use any other tracer. All OpenTelemetry spans will be picked up by Sentry automatically. +You can also use any other tracer. With `enableOpenTelemetrySetup: true`, every OpenTelemetry span is picked up by Sentry automatically. ## Modifying the default OpenTelemetry TracerProvider -You can access the tracer provider set up by Sentry when using Sentry's default OpenTelemetry instrumentation. +This is the one part of this page that needs `enableOpenTelemetrySetup: true`. `client.traceProvider` holds the tracer provider the SDK registered, and it stays `undefined` when you register a provider of your own, where you already have a reference to it. ```javascript {tabTitle: ESM} import * as Sentry from "@sentry/node"; const provider = Sentry.getClient()?.traceProvider; ``` -```javascript {tabTitle: CJS} -const Sentry = require("@sentry/node"); - -const provider = Sentry.getClient()?.traceProvider; -``` - -## Adding Additional Span Processors - -You can add additional span processors to the tracer provider set up by Sentry when using Sentry's default OpenTelemetry instrumentation. - -```javascript {tabTitle: ESM} -import * as Sentry from "@sentry/node"; -Sentry.init({ - dsn: "___DSN___", - - // The SentrySampler will use this to determine which traces to sample - tracesSampleRate: 1.0, - - // Add additional OpenTelemetry SpanProcessors: - openTelemetrySpanProcessors: [new MySpanProcessor()], -}); -``` ```javascript {tabTitle: CJS} const Sentry = require("@sentry/node"); -Sentry.init({ - dsn: "___DSN___", - - // The SentrySampler will use this to determine which traces to sample - tracesSampleRate: 1.0, - - // Add additional OpenTelemetry SpanProcessors: - openTelemetrySpanProcessors: [new MySpanProcessor()], -}); +const provider = Sentry.getClient()?.traceProvider; ``` diff --git a/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis__v10.x.mdx b/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis__v10.x.mdx new file mode 100644 index 0000000000000..1e978433e61cc --- /dev/null +++ b/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis__v10.x.mdx @@ -0,0 +1,153 @@ +--- +title: Using OpenTelemetry APIs +description: "Learn how to use OpenTelemetry APIs with Sentry." +noindex: true # Not indexed because it is a versioned docs page +supported: + - javascript.nextjs + - javascript.node + - javascript.eve + - javascript.aws-lambda + - javascript.azure-functions + - javascript.bun + - javascript.connect + - javascript.express + - javascript.fastify + - javascript.gcp-functions + - javascript.hapi + - javascript.hono + - javascript.koa + - javascript.nestjs + - javascript.nitro + - javascript.nuxt + - javascript.solidstart + - javascript.sveltekit + - javascript.astro + - javascript.remix + - javascript.react-router + - javascript.tanstackstart-react +notSupported: + - javascript +sidebar_order: 1 +--- + +Sentry supports OpenTelemetry APIs out of the box. Any spans started using OpenTelemetry APIs will be automatically captured by Sentry, while any spans started using the Sentry SDK will be automatically propagated to OpenTelemetry. + +## Adding Additional OpenTelemetry Instrumentation + +While the Sentry SDK includes some OpenTelemetry instrumentation out of the box, you may want to add additional instrumentation to your application. This can be done by registering the instrumentation through OpenTelemetry like the example below: + +```javascript {tabTitle: ESM} {12-13} +import * as Sentry from "@sentry/node"; +import { + GenericPoolInstrumentation, +} from "@opentelemetry/instrumentation-generic-pool"; + +Sentry.init({ + dsn: "___DSN___", + + // The SentrySampler will use this to determine which traces to sample + tracesSampleRate: 1.0, + + // Add additional OpenTelemetry instrumentation: + openTelemetryInstrumentations: [new GenericPoolInstrumentation()], +}); +``` +```javascript {tabTitle: CJS} {12-13} +const Sentry = require("@sentry/node"); +const { + GenericPoolInstrumentation, +} = require("@opentelemetry/instrumentation-generic-pool"); + +Sentry.init({ + dsn: "___DSN___", + + // The SentrySampler will use this to determine which traces to sample + tracesSampleRate: 1.0, + + // Add additional OpenTelemetry instrumentation: + openTelemetryInstrumentations: [new GenericPoolInstrumentation()], +}); +``` + + + It is possible to add instrumentations via `registerInstrumentations()` from + `@opentelemetry/instrumentation`. However, with ESM (`import`/`export` syntax) + you need to be careful to do so before importing any modules that should be + instrumented. + +As a rule of thumb, `registerInstrumentations()` should be called right after, and in the same context as registering ESM Loaders. + + + +## Using an OpenTelemetry Tracer + +We recommend using `Sentry.startSpan()` and related APIs to create spans, but you can also create spans using native OpenTelemetry APIs. + +You can access the tracer Sentry uses via `client.tracer` and then create spans with OpenTelemetry APIs, as shown below: + +```javascript {tabTitle: ESM} +import * as Sentry from "@sentry/node"; + +const tracer = Sentry.getClient()?.tracer; +// Now you can use native APIs on the tracer: +tracer.startActiveSpan("span name", () => { + // measure something +}); +``` +```javascript {tabTitle: CJS} +const Sentry = require("@sentry/node"); + +const tracer = Sentry.getClient()?.tracer; +// Now you can use native APIs on the tracer: +tracer.startActiveSpan("span name", () => { + // measure something +}); +``` + +You can also use any other tracer. All OpenTelemetry spans will be picked up by Sentry automatically. + +## Modifying the default OpenTelemetry TracerProvider + +You can access the tracer provider set up by Sentry when using Sentry's default OpenTelemetry instrumentation. + +```javascript {tabTitle: ESM} +import * as Sentry from "@sentry/node"; + +const provider = Sentry.getClient()?.traceProvider; +``` +```javascript {tabTitle: CJS} +const Sentry = require("@sentry/node"); + +const provider = Sentry.getClient()?.traceProvider; +``` + +## Adding Additional Span Processors + +You can add additional span processors to the tracer provider set up by Sentry when using Sentry's default OpenTelemetry instrumentation. + +```javascript {tabTitle: ESM} +import * as Sentry from "@sentry/node"; + +Sentry.init({ + dsn: "___DSN___", + + // The SentrySampler will use this to determine which traces to sample + tracesSampleRate: 1.0, + + // Add additional OpenTelemetry SpanProcessors: + openTelemetrySpanProcessors: [new MySpanProcessor()], +}); +``` +```javascript {tabTitle: CJS} +const Sentry = require("@sentry/node"); + +Sentry.init({ + dsn: "___DSN___", + + // The SentrySampler will use this to determine which traces to sample + tracesSampleRate: 1.0, + + // Add additional OpenTelemetry SpanProcessors: + openTelemetrySpanProcessors: [new MySpanProcessor()], +}); +``` diff --git a/redirects.js b/redirects.js index 788d5d4a203f1..5664b5e1995b6 100644 --- a/redirects.js +++ b/redirects.js @@ -970,6 +970,41 @@ const userDocsRedirects = [ source: '/platforms/javascript/guides/aws-lambda/cjs-npm__v9.x/', destination: '/platforms/javascript/guides/aws-lambda/install/cjs-npm__v9.x/', }, + { + source: '/platforms/javascript/guides/node/install/lightweight/', + destination: + '/platforms/javascript/guides/node/configuration/integrations/opentelemetry/', + }, + { + source: '/platforms/javascript/guides/connect/install/lightweight/', + destination: + '/platforms/javascript/guides/connect/configuration/integrations/opentelemetry/', + }, + { + source: '/platforms/javascript/guides/express/install/lightweight/', + destination: + '/platforms/javascript/guides/express/configuration/integrations/opentelemetry/', + }, + { + source: '/platforms/javascript/guides/fastify/install/lightweight/', + destination: + '/platforms/javascript/guides/fastify/configuration/integrations/opentelemetry/', + }, + { + source: '/platforms/javascript/guides/hapi/install/lightweight/', + destination: + '/platforms/javascript/guides/hapi/configuration/integrations/opentelemetry/', + }, + { + source: '/platforms/javascript/guides/hono/install/lightweight/', + destination: + '/platforms/javascript/guides/hono/configuration/integrations/opentelemetry/', + }, + { + source: '/platforms/javascript/guides/koa/install/lightweight/', + destination: + '/platforms/javascript/guides/koa/configuration/integrations/opentelemetry/', + }, { source: '/platforms/javascript/guides/react-router/features/instrumentation-api/', destination: '/platforms/javascript/guides/react-router/manual-setup/', @@ -2296,14 +2331,11 @@ const userDocsRedirects = [ // Cloudflare setup pages moved from Features to Installation Methods. { source: '/platforms/javascript/guides/cloudflare/features/vite-plugin.md', - destination: - '/platforms/javascript/guides/cloudflare/install/vite-plugin.md', + destination: '/platforms/javascript/guides/cloudflare/install/vite-plugin.md', }, { - source: - '/platforms/javascript/guides/cloudflare/features/vite-plugin/:path*', - destination: - '/platforms/javascript/guides/cloudflare/install/vite-plugin/:path*', + source: '/platforms/javascript/guides/cloudflare/features/vite-plugin/:path*', + destination: '/platforms/javascript/guides/cloudflare/install/vite-plugin/:path*', }, // Cloudflare AI pages moved from Features to Agent Tracing. {