Using Your Existing OpenTelemetry Setup

Learn how to use your existing custom OpenTelemetry setup with Sentry.

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:

Copied
const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
const Sentry = require("@sentry/node");
const {
  SentrySpanProcessor,
  SentryPropagator,
  SentrySampler,
} = require("@sentry/opentelemetry");

const sentryClient = Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  skipOpenTelemetrySetup: true,

  // The SentrySampler will use this to determine which traces to sample
  tracesSampleRate: 1.0,
});

// Note: This could be BasicTracerProvider or any other provider depending on
// how you are using the OpenTelemetry SDK
const provider = new NodeTracerProvider({
  // Ensure the correct subset of traces is sent to Sentry
  // This also ensures trace propagation works as expected
  sampler: sentryClient ? new SentrySampler(sentryClient) : undefined,
});

// Ensure spans are correctly linked & sent to Sentry
provider.addSpanProcessor(new SentrySpanProcessor());

provider.register({
  // Ensure trace propagation works
  // This relies on the SentrySampler for correct propagation
  propagator: new SentryPropagator(),
  // Ensure context & request isolation are correctly managed
  contextManager: new Sentry.SentryContextManager(),
});

// Validate that the setup is correct
Sentry.validateOpenTelemetrySetup();

Make sure that all Required OpenTelemetry Instrumentation is set up correctly. Otherwise, the Sentry SDK may not work as expected.

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 if you want to use a custom sampler.
  • SentryPropagator: Ensures that trace propagation works correctly.
  • 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.

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:

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:

Available since SDK version 8.35.0

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:

Copied
const sentryClient = Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  skipOpenTelemetrySetup: true,
  integrations: [Sentry.httpIntegration({ spans: false })],
});

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.

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.

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:

Copied
const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
const Sentry = require("@sentry/node");
const {
  SentrySpanProcessor,
  SentryPropagator,
  SentrySampler,
  wrapSamplingDecision,
} = require("@sentry/opentelemetry");

// implements Sampler from "@opentelemetry/sdk-trace-node"
class CustomSampler {
  shouldSample(
    context,
    _traceId,
    _spanName,
    _spanKind,
    attributes,
    _links,
  ) {
    const decision = yourDecisionLogic();

    // wrap the result
    return wrapSamplingDecision({
      decision,
      context,
      spanAttributes: attributes,
    });
  }

  toString() {
    return CustomSampler.name;
  }
}

const sentryClient = Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  skipOpenTelemetrySetup: true,

  // By defining any sample rate,
  // tracing intergations will be added by default
  // omit this if you do not want any performance integrations to be added
  tracesSampleRate: 0,
});

const provider = new NodeTracerProvider({
  sampler: new CustomSampler(),
});

// ...rest of your setup

// Validate that the setup is correct
Sentry.validateOpenTelemetrySetup();

If your application is running in ESM (import/export syntax), OpenTelemetry requires a special setup to work correctly. The Sentry SDK will automatically detect if your application is running in ESM mode and by default register a loader hook itself. If you are also registering a loader hook, you need to disable Sentry's loader hook:

Copied
Sentry.init({
  skipOpenTelemetrySetup: true,
  registerEsmLoaderHooks: false,
});

Registering loader hooks multiple times might result in duplicated spans being created. More details.

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.
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").