Last active
August 3, 2025 13:46
-
-
Save hnykda/180ac0e87558ed9b0dcf548b1d07b870 to your computer and use it in GitHub Desktop.
sentry and open telemetry with standard OTEL/W3CT propagation nodejs/nextjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this file is loaded instrumentation.js via something like this: | |
// export async function register() {if (process.env.NEXT_RUNTIME === "nodejs"){await import("../sentry.server.config");}} | |
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; | |
import { Resource, resourceFromAttributes } from "@opentelemetry/resources"; | |
import { | |
W3CTraceContextPropagator, | |
CompositePropagator, | |
} from "@opentelemetry/core"; | |
import { | |
NodeTracerProvider, | |
SimpleSpanProcessor, | |
ConsoleSpanExporter, | |
BatchSpanProcessor, | |
} from "@opentelemetry/sdk-trace-node"; | |
import * as Sentry from "@sentry/nextjs"; | |
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions"; | |
import { env } from "next-runtime-env"; | |
import { | |
SentryPropagator, | |
SentrySampler, | |
SentrySpanProcessor, | |
} from "@sentry/opentelemetry"; | |
import { registerInstrumentations } from "@opentelemetry/instrumentation"; | |
import { UndiciInstrumentation } from "@opentelemetry/instrumentation-undici"; | |
import { Context, propagation, TextMapSetter } from "@opentelemetry/api"; | |
// import { trace } from "@opentelemetry/api"; | |
// uncomment this to see some extra debug info | |
// import { diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api"; | |
// diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); | |
// Initialize Sentry with custom OpenTelemetry setup | |
const sentryClient = Sentry.init({ | |
dsn: env("NEXT_PUBLIC_SENTRY_DSN"), | |
environment: env("ENVIRONMENT"), | |
skipOpenTelemetrySetup: true, | |
tracesSampleRate: 1.0, | |
// Setting this option to true will print useful information to the console while you're setting up Sentry. | |
// true will only work if disableLogger is false in next.config.ts | |
debug: false, | |
}); | |
const otlpExporter = new OTLPTraceExporter({ | |
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT | |
? `${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces` | |
: "http://localhost:4318/v1/traces", | |
}); | |
// https://docs.sentry.io/platforms/javascript/guides/node/opentelemetry/custom-setup/ | |
const provider = new NodeTracerProvider({ | |
resource: resourceFromAttributes({ | |
[ATTR_SERVICE_NAME]: "your-service-name", | |
}), | |
// @ts-expect-error - SentrySampler is not typed correctly | |
sampler: sentryClient ? new SentrySampler(sentryClient) : undefined, | |
spanProcessors: [ | |
// new SimpleSpanProcessor(new ConsoleSpanExporter()), // useful for debugging | |
// @ts-expect-error - SentrySpanProcessor is not typed correctly | |
new SentrySpanProcessor(), | |
new BatchSpanProcessor(otlpExporter), | |
], | |
}); | |
provider.register({ | |
propagator: new CompositePropagator({ | |
// W3CTraceContextPropagator is OTEL stadnard, makes sure that e.g. `traceparent` is included in requests | |
propagators: [new W3CTraceContextPropagator(), new SentryPropagator()], | |
}), | |
contextManager: new Sentry.SentryContextManager(), | |
}); | |
Sentry.validateOpenTelemetrySetup(); | |
registerInstrumentations({ | |
// actually adds traceparent into headers when calling fetch | |
instrumentations: [new UndiciInstrumentation()], | |
}); | |
// ways to instrument your specific calls/code/... would be somewhere on the BE of your Node app (or e.g. NextJS backend) | |
// trace.getTracer("cohort-portal").startActiveSpan("test", (span) => { | |
// console.log("test", span); | |
// fetch("http://example.com") // example.com should receive a request with header that has sentry-trace and traceparent | |
// span.end(); | |
// }); | |
// also works, sentry recommends this | |
// Sentry.getClient()?.tracer.startActiveSpan("test", (span) => { | |
// console.log("test 2", span); | |
// span.end(); | |
// }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment