From d9bdc79729474c26ee90ef39a65a1b5804e746e5 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 28 Nov 2024 13:25:58 +0100 Subject: [PATCH] Guide towards v9 for ESM OTEL setups (#11974) --- .../javascript/common/install/esm.mdx | 2 + .../common/opentelemetry/custom-setup.mdx | 76 ++++++++++++++----- .../using-opentelemetry-apis.mdx | 18 +++-- 3 files changed, 74 insertions(+), 22 deletions(-) diff --git a/docs/platforms/javascript/common/install/esm.mdx b/docs/platforms/javascript/common/install/esm.mdx index d8d8ceea8b970..82657e0655d40 100644 --- a/docs/platforms/javascript/common/install/esm.mdx +++ b/docs/platforms/javascript/common/install/esm.mdx @@ -75,6 +75,8 @@ Sentry.init({ }); ``` +{/* TODO(v9): This will become the default behavior and registerEsmLoaderHooks will no longer accept an object. So I guess we should remove this section when v9 ships. */} + If you are starting Sentry via `--import`, you can instruct `import-in-the-middle` to only wrap packages that Sentry specifically instruments. To do this, you can set the `onlyIncludeInstrumentedModules` to `true`: diff --git a/docs/platforms/javascript/common/opentelemetry/custom-setup.mdx b/docs/platforms/javascript/common/opentelemetry/custom-setup.mdx index e39ea40ae68fc..b7691e092e646 100644 --- a/docs/platforms/javascript/common/opentelemetry/custom-setup.mdx +++ b/docs/platforms/javascript/common/opentelemetry/custom-setup.mdx @@ -23,6 +23,14 @@ 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. + +If you are looking to simply add individual OpenTelemetry instrumentation to your Sentry setup, you should read Adding Additional OpenTelemetry Instrumentation instead. + + + To use an existing OpenTelemetry setup, set `skipOpenTelemetrySetup: true` in your `init({})` config, then set up all the components that Sentry needs yourself. Finish by installing `@sentry/opentelemetry` and adding the following: ```javascript @@ -71,7 +79,6 @@ Make sure that all [Required OpenTelemetry Instrumentation](./#required-instrume 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:** @@ -86,7 +93,13 @@ In order for the Sentry SDK to work as expected, and for it to be in sync with O - **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. + 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. + ## Required Instrumentation @@ -95,13 +108,24 @@ By default, Sentry will register OpenTelemetry instrumentation to automatically 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 */} + - httpIntegration registers [@opentelemetry/instrumentation-http](https://www.npmjs.com/package/@opentelemetry/instrumentation-http) - nativeNodeFetchIntegration registers [opentelemetry-instrumentation-fetch-node](https://www.npmjs.com/package/opentelemetry-instrumentation-fetch-node) - +{/* 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. + 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 + + . @@ -140,7 +164,7 @@ const { SentrySpanProcessor, SentryPropagator, SentrySampler, - wrapSamplingDecision + wrapSamplingDecision, } = require("@sentry/opentelemetry"); // implements Sampler from "@opentelemetry/sdk-trace-node" @@ -180,11 +204,14 @@ const provider = new NodeTracerProvider({ // Validate that the setup is correct Sentry.validateOpenTelemetrySetup(); ``` + ## ESM Loaders -If your application is running in ESM (`import`/`export` syntax), OpenTelemetry requires a [special setup](https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md) to work correctly. -The Sentry SDK will automatically detect if your application is running in ESM mode and by default [register a loader hook](https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md#instrumentation-hook-required-for-esm) itself. -If you are also registering a loader hook, you need to disable Sentry's loader hook: +If your application is running in ESM (`import`/`export` syntax), OpenTelemetry requires you to set up _ESM loader hooks_. + +The Sentry SDK will automatically register ESM loader hooks by default. +However, if you have your own OpenTelemetry setup, it is recommended to configure the Sentry SDK to not register these hooks and instead register them yourself. +You can do so by setting `registerEsmLoaderHooks` to `false` and [setting up ESM loader hooks](https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md#instrumentation-hook-required-for-esm): ```javascript Sentry.init({ @@ -193,15 +220,30 @@ Sentry.init({ }); ``` - + -Registering loader hooks multiple times might result in duplicated spans being created. -[More details.](https://github.com/getsentry/sentry-javascript/issues/14065#issuecomment-2435546961) +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. + + -Alternatively, you can also use Sentry's loader hook and remove your own loader hook registration code. -In this case, ensure that you initialize the Sentry SDK in its own file and load this file prior to your application via `node --import instrument.mjs your-app.mjs`. - -Learn more about ESM installation methods. + + + + Learn more about ESM installation methods. + + diff --git a/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis.mdx b/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis.mdx index 46a3d21133242..5bb0cbfaa245a 100644 --- a/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis.mdx +++ b/docs/platforms/javascript/common/opentelemetry/using-opentelemetry-apis.mdx @@ -29,7 +29,7 @@ Sentry supports OpenTelemetry APIs out of the box. Any spans started using OpenT 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 +```javascript {12-13} const Sentry = require("@sentry/node"); const { GenericPoolInstrumentation, @@ -40,13 +40,21 @@ Sentry.init({ // The SentrySampler will use this to determine which traces to sample tracesSampleRate: 1.0, -}); -// Afterwards, you can add additional instrumentation: -Sentry.addOpenTelemetryInstrumentation(new GenericPoolInstrumentation()); + // Add additional OpenTelemetry instrumentation: + openTelemetryInstrumentations: [new GenericPoolInstrumentation()], +}); ``` -Any instrumentation added like this or via `registerInstrumentations()` from `@opentelemetry/instrumentation` will be picked up by Sentry. + + 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