diff --git a/MIGRATION.md b/MIGRATION.md index dea7dfa7bf7c..ade93d4c1655 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -119,7 +119,7 @@ Spans go to Sentry. This is not a general OpenTelemetry pipeline: there is no ex ##### 3. Your own OpenTelemetry, Sentry linked to it -Turn Sentry tracing off, run your own OpenTelemetry setup, and add the Sentry `otlpIntegration()`. Leave `enableOpenTelemetrySetup` unset or set it to `false`: +Turn Sentry tracing off, run your own OpenTelemetry setup, and add the Sentry `openTelemetryIntegration()`. Leave `enableOpenTelemetrySetup` unset or set it to `false`: ```js import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; @@ -136,13 +136,13 @@ provider.register(); Sentry.init({ dsn: '__DSN__', // no tracesSampleRate: OpenTelemetry owns spans, Sentry owns errors and logs - integrations: [Sentry.otlpIntegration()], + integrations: [Sentry.openTelemetryIntegration()], }); ``` `enableOpenTelemetrySetup` already defaults to `false` on most server SDKs, so there is nothing to set. On `@sentry/nextjs` and `@sentry/sveltekit` it defaults to `true`, so you have to set it to `false` explicitly. Otherwise Sentry registers its own tracer provider and you end up in setup 2 rather than this one. -Spans are completely managed by your OpenTelemetry setup and the two pipelines stay separate: Sentry sends no spans, and no Sentry span is exported to your OpenTelemetry pipeline. Sentry captures errors and logs, and the Sentry `otlpIntegration()` attaches them to the active OpenTelemetry span so all your telemetry is connected in one trace. `getOtlpTracesEndpoint()` turns your DSN into the URL and auth headers for Sentry's OTLP endpoint, so you can point your own exporter at Sentry, at your own collector, or at both. +Spans are completely managed by your OpenTelemetry setup and the two pipelines stay separate: Sentry sends no spans, and no Sentry span is exported to your OpenTelemetry pipeline. Sentry captures errors and logs, and the Sentry `openTelemetryIntegration()` attaches them to the active OpenTelemetry span so all your telemetry is connected in one trace. `getOtlpTracesEndpoint()` turns your DSN into the URL and auth headers for Sentry's OTLP endpoint, so you can point your own exporter at Sentry, at your own collector, or at both. Sentry does not touch your pipeline: no exporter, no span processor, no tracer provider, and outgoing trace propagation is left to your propagator. See [Connecting Sentry to your OpenTelemetry traces](#connecting-sentry-to-your-opentelemetry-traces) for the details, including what changed if you used the v10 integration. @@ -158,13 +158,13 @@ In v10, running your own OpenTelemetry setup meant registering Sentry's own comp #### Connecting Sentry to your OpenTelemetry traces -`Sentry.otlpIntegration()` attaches everything Sentry sends that carries trace information (errors, logs, metrics and crons) to the OpenTelemetry span that is active when it happens. It takes no options, and is available from every server-side SDK, so there is nothing extra to install or import. See [setup 3](#3-your-own-opentelemetry-sentry-linked-to-it) above for a complete example. +`Sentry.openTelemetryIntegration()` attaches everything Sentry sends that carries trace information (errors, logs, metrics and crons) to the OpenTelemetry span that is active when it happens. It takes no options, and is available from every server-side SDK, so there is nothing extra to install or import. See [setup 3](#3-your-own-opentelemetry-sentry-linked-to-it) above for a complete example. It does not set up a span exporter, span processor, or tracer provider. You keep full ownership of your OpenTelemetry pipeline, and outgoing request propagation is left to your OpenTelemetry propagator. To send your spans to Sentry, point your own exporter at the URL and auth headers that `Sentry.getOtlpTracesEndpoint()` derives from your DSN. An active Sentry span still takes precedence, so this only changes what happens when Sentry has no span of its own, which is the usual setup when OpenTelemetry owns tracing. -If you used the v10 integration from `@sentry/node-core/light/otlp`, three things changed: it moved to the main export of every server SDK, it [no longer sets up an exporter for you and lost its options](#3-removed-apis), and it [reports itself as `Otlp` rather than `OtlpIntegration`](#otlpintegration-integration-renamed-to-otlp). Configure your own exporter as shown in setup 3, pointing it at your collector's URL if you route through one. +If you used the v10 integration from `@sentry/node-core/light/otlp`, three things changed: it moved to the main export of every server SDK, it [no longer sets up an exporter for you and lost its options](#3-removed-apis), and it [was renamed to `openTelemetryIntegration()`](#otlpintegration-renamed-to-opentelemetryintegration). Configure your own exporter as shown in setup 3, pointing it at your collector's URL if you route through one. ### `sendDefaultPii` is replaced by `dataCollection` @@ -1334,8 +1334,8 @@ The `idleTimeout`, `finalTimeout` and `childSpanTimeout` options of interaction - (Express) The `shouldHandleError` option was removed from `setupExpressErrorHandler` and `expressErrorHandler`, along with the `ExpressHandlerOptions` type. Configure it on `expressIntegration()` instead. See [Express: errors are captured automatically](#express-errors-are-captured-automatically). - (Express) `ExpressIntegrationOptions` is no longer exported from `@sentry/core`. Import it from `@sentry/node` instead — that version is the one `expressIntegration()` accepts, and it carries `shouldHandleError`. - (Fastify) The deprecated `instrumentFastify` and `handleFastifyError` exports were removed. `fastifyIntegration` now instruments Fastify (v3.21–v5) and captures errors on its own, so neither export is needed. See [Fastify: `setupFastifyErrorHandler` is deprecated](#fastify-setupfastifyerrorhandler-is-deprecated). -- The `@sentry/node-core/light/otlp` entry point was removed, along with its optional `@opentelemetry/exporter-trace-otlp-http` peer dependency. `otlpIntegration` is now exported directly from every server-side SDK, so `Sentry.otlpIntegration()` needs no extra import or install. -- The `otlpIntegration` options `setupOtlpTracesExporter` and `collectorUrl` were removed, and the integration no longer sets up a span exporter, span processor, or tracer provider. Configure your own exporter and point it at `Sentry.getOtlpTracesEndpoint(dsn)`, or at your collector's URL if you route through one. See [Connecting Sentry to your OpenTelemetry traces](#connecting-sentry-to-your-opentelemetry-traces). +- The `@sentry/node-core/light/otlp` entry point was removed, along with its optional `@opentelemetry/exporter-trace-otlp-http` peer dependency. `openTelemetryIntegration` is now exported directly from every server-side SDK, so `Sentry.openTelemetryIntegration()` needs no extra import or install. +- The `setupOtlpTracesExporter` and `collectorUrl` options were removed, and the integration no longer sets up a span exporter, span processor, or tracer provider. Configure your own exporter and point it at `Sentry.getOtlpTracesEndpoint(dsn)`, or at your collector's URL if you route through one. See [Connecting Sentry to your OpenTelemetry traces](#connecting-sentry-to-your-opentelemetry-traces). - The deprecated `httpServerSpansIntegration` `instrumentation.{requestHook,responseHook,applyCustomAttributesOnSpan}` option was removed. Use `onSpanCreated` instead. `httpServerSpansIntegration` only covers incoming requests; the outgoing hooks (`outgoingRequestHook`, `outgoingResponseHook`, `outgoingRequestApplyCustomAttributes`) are on `httpIntegration`. #### `httpIntegration` options were consolidated @@ -1930,11 +1930,27 @@ Sentry.denoHttpIntegration({ }); ``` -### `OtlpIntegration` integration renamed to `Otlp` +### `otlpIntegration` renamed to `openTelemetryIntegration` Affected SDKs: Server-side SDKs (`@sentry/node` and all dependents). -The OTLP integration reports itself as `Otlp` rather than `OtlpIntegration`, matching every other integration in the SDKs, none of which carry an `Integration` suffix in their name. The `otlpIntegration()` export itself is unchanged. This only matters if you reference the integration by name: +The old name was misleading: the integration sends nothing over OTLP. It sets up no exporter, no span processor and no tracer provider, and only connects what Sentry sends to your OpenTelemetry traces. + +```js +// before +Sentry.init({ + integrations: [Sentry.otlpIntegration()], +}); + +// after +Sentry.init({ + integrations: [Sentry.openTelemetryIntegration()], +}); +``` + +`getOtlpTracesEndpoint()` keeps its name. That helper really is about OTLP: it derives the URL and auth headers of Sentry's OTLP traces endpoint from your DSN. + +The integration also reports itself as `OpenTelemetry` rather than `OtlpIntegration`, which matters if you reference it by name: ```js // before @@ -1944,7 +1960,7 @@ Sentry.init({ // after Sentry.init({ - integrations: integrations => integrations.filter(integration => integration.name !== 'Otlp'), + integrations: integrations => integrations.filter(integration => integration.name !== 'OpenTelemetry'), }); ``` diff --git a/dev-packages/e2e-tests/test-applications/nextjs-otlp/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-otlp/sentry.server.config.ts index 8aac811122de..054b53b113a4 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-otlp/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-otlp/sentry.server.config.ts @@ -12,5 +12,5 @@ Sentry.init({ enableOpenTelemetrySetup: false, // Puts the active OpenTelemetry span's trace on everything Sentry sends. - integrations: [Sentry.otlpIntegration()], + integrations: [Sentry.openTelemetryIntegration()], }); diff --git a/dev-packages/e2e-tests/test-applications/node-express-otlp/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express-otlp/src/app.ts index f4e0fc622407..c6246a18f3a9 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-otlp/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-otlp/src/app.ts @@ -35,7 +35,7 @@ Sentry.init({ dsn, debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server - integrations: [Sentry.otlpIntegration()], + integrations: [Sentry.openTelemetryIntegration()], }); interface ExportedTrace { diff --git a/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/src/instrument.mjs b/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/src/instrument.mjs index a37cba30293f..25749a79ff21 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/src/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/src/instrument.mjs @@ -28,5 +28,5 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server // no tracesSampleRate: OpenTelemetry owns spans, Sentry owns errors and logs - integrations: [Sentry.otlpIntegration()], + integrations: [Sentry.openTelemetryIntegration()], }); diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts index 7e34a1727574..5bb4e99fbb59 100644 --- a/packages/astro/src/index.server.ts +++ b/packages/astro/src/index.server.ts @@ -99,7 +99,7 @@ export { postgresIntegration, postgresJsIntegration, prismaIntegration, - otlpIntegration, + openTelemetryIntegration, getOtlpTracesEndpoint, processSessionIntegration, childProcessIntegration, diff --git a/packages/aws-serverless/src/index.ts b/packages/aws-serverless/src/index.ts index d48be039ba2f..19b48bc6fb86 100644 --- a/packages/aws-serverless/src/index.ts +++ b/packages/aws-serverless/src/index.ts @@ -119,7 +119,7 @@ export { postgresJsIntegration, processSessionIntegration, prismaIntegration, - otlpIntegration, + openTelemetryIntegration, getOtlpTracesEndpoint, childProcessIntegration, workerThreadsIntegration, diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index 5bae62b97c69..03248fc22f4d 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -139,7 +139,7 @@ export { postgresIntegration, postgresJsIntegration, prismaIntegration, - otlpIntegration, + openTelemetryIntegration, getOtlpTracesEndpoint, processSessionIntegration, hapiIntegration, diff --git a/packages/cloudflare/src/index.ts b/packages/cloudflare/src/index.ts index d114590262bf..4e24fd9b0ecb 100644 --- a/packages/cloudflare/src/index.ts +++ b/packages/cloudflare/src/index.ts @@ -120,7 +120,7 @@ export { httpServerIntegration } from './integrations/httpServer'; export { fetchIntegration } from './integrations/fetch'; export { spotlightIntegration } from './integrations/spotlight'; export { - otlpIntegration, + openTelemetryIntegration, getOtlpTracesEndpoint, prismaIntegration, instrumentOpenAiClient, diff --git a/packages/core/src/carrier.ts b/packages/core/src/carrier.ts index 369f1d95d8fe..cf48f39c7f4d 100644 --- a/packages/core/src/carrier.ts +++ b/packages/core/src/carrier.ts @@ -43,7 +43,7 @@ export interface SentryCarrier { /** Strategy for assembling segment spans into transactions; set by SDKs that defer capture. */ segmentSpanCaptureStrategy?: SegmentSpanCaptureStrategy; - /** Supplies trace context from a non-Sentry source (e.g. OpenTelemetry); set by `otlpIntegration`. */ + /** Supplies trace context from a non-Sentry source (e.g. OpenTelemetry); set by `openTelemetryIntegration`. */ externalPropagationContextProvider?: () => { traceId: string; spanId: string } | undefined; /** Overwrites TextEncoder used in `@sentry/core`, need for `react-native@0.73` and older */ diff --git a/packages/deno/src/index.ts b/packages/deno/src/index.ts index aa3fa1babba8..461bf5be6a8e 100644 --- a/packages/deno/src/index.ts +++ b/packages/deno/src/index.ts @@ -142,7 +142,7 @@ export { postgresJsIntegration, tediousIntegration, } from '@sentry/server-utils'; -export { otlpIntegration, getOtlpTracesEndpoint } from '@sentry/server-utils/no-diagnostic-channels'; +export { openTelemetryIntegration, getOtlpTracesEndpoint } from '@sentry/server-utils/no-diagnostic-channels'; // Deprecated aliases kept for back-compat. Each forwards to the shared // integration above, so its name is the shared name (e.g. `Mysql`), not the old // `Deno*` name. See each alias's `@deprecated` note. diff --git a/packages/google-cloud-serverless/src/index.ts b/packages/google-cloud-serverless/src/index.ts index 49f441e653d1..d55e878d21ef 100644 --- a/packages/google-cloud-serverless/src/index.ts +++ b/packages/google-cloud-serverless/src/index.ts @@ -118,7 +118,7 @@ export { postgresIntegration, postgresJsIntegration, prismaIntegration, - otlpIntegration, + openTelemetryIntegration, getOtlpTracesEndpoint, processSessionIntegration, hapiIntegration, diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 3b18ac957f07..7eafc647ae0d 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -32,7 +32,7 @@ export { vercelAIIntegration, } from '@sentry/server-utils'; export { - otlpIntegration, + openTelemetryIntegration, getOtlpTracesEndpoint, prismaIntegration, instrumentOpenAiClient, diff --git a/packages/server-utils/src/exports.ts b/packages/server-utils/src/exports.ts index 9baca0c266f6..10e0f23e0989 100644 --- a/packages/server-utils/src/exports.ts +++ b/packages/server-utils/src/exports.ts @@ -1,5 +1,5 @@ // Shared exports not using diagnostics channels export { setHttpServerSpanRouteAttribute } from './utils/setHttpServerSpanRouteAttribute'; export { setAsyncLocalStorageAsyncContextStrategy } from './async-context'; -export { otlpIntegration, getOtlpTracesEndpoint } from './otlp'; +export { openTelemetryIntegration, getOtlpTracesEndpoint } from './opentelemetry'; export * from './ai'; diff --git a/packages/server-utils/src/otlp.ts b/packages/server-utils/src/opentelemetry.ts similarity index 92% rename from packages/server-utils/src/otlp.ts rename to packages/server-utils/src/opentelemetry.ts index e0d925788dd7..f030aaaaaf8f 100644 --- a/packages/server-utils/src/otlp.ts +++ b/packages/server-utils/src/opentelemetry.ts @@ -2,9 +2,9 @@ import { isSpanContextValid, trace } from '@opentelemetry/api'; import type { IntegrationFn } from '@sentry/core'; import { defineIntegration, dsnFromString, SENTRY_API_VERSION, registerExternalPropagationContext } from '@sentry/core'; -const INTEGRATION_NAME = 'Otlp' as const; +const INTEGRATION_NAME = 'OpenTelemetry' as const; -const _otlpIntegration = (() => { +const _openTelemetryIntegration = (() => { return { name: INTEGRATION_NAME, @@ -44,7 +44,7 @@ const _otlpIntegration = (() => { * This does not export any spans. Configure your own span exporter and point it at Sentry using * {@link getOtlpTracesEndpoint}. */ -export const otlpIntegration = defineIntegration(_otlpIntegration); +export const openTelemetryIntegration = defineIntegration(_openTelemetryIntegration); /** * Builds the URL and auth headers for Sentry's OTLP traces endpoint, to configure an @@ -69,7 +69,7 @@ export const otlpIntegration = defineIntegration(_otlpIntegration); * * Sentry.init({ * dsn: '__DSN__', - * integrations: [Sentry.otlpIntegration()], + * integrations: [Sentry.openTelemetryIntegration()], * }); * ``` */ diff --git a/packages/server-utils/test/otlp.test.ts b/packages/server-utils/test/opentelemetry.test.ts similarity index 91% rename from packages/server-utils/test/otlp.test.ts rename to packages/server-utils/test/opentelemetry.test.ts index 05cf6f581bda..6c8e971ebbbd 100644 --- a/packages/server-utils/test/otlp.test.ts +++ b/packages/server-utils/test/opentelemetry.test.ts @@ -3,7 +3,7 @@ import { context, INVALID_SPAN_CONTEXT, ROOT_CONTEXT, trace, TraceFlags } from ' import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import type { Envelope } from '@sentry/core'; import { getCurrentScope, getMainCarrier, registerExternalPropagationContext, setCurrentClient } from '@sentry/core'; -import { getOtlpTracesEndpoint, otlpIntegration } from '../src/otlp'; +import { getOtlpTracesEndpoint, openTelemetryIntegration } from '../src/opentelemetry'; import { getDefaultTestClientOptions, TestClient } from './mocks/client'; const DSN = 'https://public@dsn.ingest.sentry.io/1337'; @@ -61,9 +61,9 @@ function withActiveOtelSpan(callback: () => T): T { return context.with(trace.setSpan(context.active(), otelSpan), callback); } -function setupClientWithOtlpIntegration(): TestClient { +function setupClientWithOpenTelemetryIntegration(): TestClient { const client = new TestClient( - getDefaultTestClientOptions({ dsn: DSN, integrations: [otlpIntegration()], stackParser: () => [] }), + getDefaultTestClientOptions({ dsn: DSN, integrations: [openTelemetryIntegration()], stackParser: () => [] }), ); setCurrentClient(client); client.init(); @@ -76,7 +76,7 @@ function setupClientCapturingEnvelopes(): { client: TestClient; envelopes: Envel const client = new TestClient( getDefaultTestClientOptions({ dsn: DSN, - integrations: [otlpIntegration()], + integrations: [openTelemetryIntegration()], stackParser: () => [], enableSend: true, }), @@ -87,7 +87,7 @@ function setupClientCapturingEnvelopes(): { client: TestClient; envelopes: Envel return { client, envelopes }; } -describe('otlpIntegration', () => { +describe('openTelemetryIntegration', () => { beforeEach(() => { getMainCarrier().__SENTRY__ = undefined; context.setGlobalContextManager(new SyncContextManager()); @@ -99,7 +99,7 @@ describe('otlpIntegration', () => { }); it('links captured errors to the active OpenTelemetry span', async () => { - const client = setupClientWithOtlpIntegration(); + const client = setupClientWithOpenTelemetryIntegration(); withActiveOtelSpan(() => { client.captureException(new Error('boom')); @@ -140,7 +140,7 @@ describe('otlpIntegration', () => { }); it('ignores an active span with an invalid span context', async () => { - const client = setupClientWithOtlpIntegration(); + const client = setupClientWithOpenTelemetryIntegration(); getCurrentScope().setPropagationContext({ traceId: 'cccccccccccccccccccccccccccccccc', sampleRand: 0.5 }); // OpenTelemetry hands out a span wrapping `INVALID_SPAN_CONTEXT` when tracing is suppressed, or @@ -154,7 +154,7 @@ describe('otlpIntegration', () => { }); it('falls back to the Sentry propagation context when no OpenTelemetry span is active', async () => { - const client = setupClientWithOtlpIntegration(); + const client = setupClientWithOpenTelemetryIntegration(); getCurrentScope().setPropagationContext({ traceId: 'cccccccccccccccccccccccccccccccc', sampleRand: 0.5 }); client.captureException(new Error('boom')); diff --git a/packages/vercel-edge/src/index.ts b/packages/vercel-edge/src/index.ts index 4a38cd639cc4..bc9be3e2aeef 100644 --- a/packages/vercel-edge/src/index.ts +++ b/packages/vercel-edge/src/index.ts @@ -103,7 +103,7 @@ export { } from '@sentry/core'; export { trpcMiddleware, wrapMcpServerWithSentry } from '@sentry/core/server'; export { - otlpIntegration, + openTelemetryIntegration, getOtlpTracesEndpoint, instrumentOpenAiClient, instrumentAnthropicAiClient,