UNPKG

@ogcio/o11y-sdk-node

Version:

Opentelemetry standard instrumentation SDK for NodeJS based project

77 lines (76 loc) 3.48 kB
/** * Enhances a NodeSDKConfig with Sentry integration for Next.js server-side. * * includes Next.js-specific integrations * filters Next.js internal spans (static assets, _next routes, etc...) * nextjs proper source map resolution */ export async function withSentryNextjs(config, options = {}) { const { sentryOptions = {}, useSentrySampling = false } = options; const components = await buildSentryNextjsComponents(sentryOptions, useSentrySampling); return { ...config, // Prepend SentrySpanProcessor so it processes spans before OTLP export prependSpanProcessors: [ components.spanProcessor, ...(config.prependSpanProcessors ?? []), ], // Wrap sampler with SentrySampler, using o11y's sampler as fallback samplerWrapper: (defaultSampler) => { // Chain with any existing wrapper const baseSampler = config.samplerWrapper ? config.samplerWrapper(defaultSampler) : defaultSampler; return components.sampler(baseSampler); }, // Add SentryPropagator for distributed tracing additionalPropagators: [ components.propagator, ...(config.additionalPropagators ?? []), ], // Use SentryContextManager for proper async context tracking contextManager: config.contextManager ?? components.contextManager, // Validate Sentry setup after SDK starts onSdkStarted: (sdk) => { components.validate(); config.onSdkStarted?.(sdk); }, }; } /** * Builds Sentry OTEL components for Next.js by dynamically importing @sentry packages. * This keeps @sentry/* as optional peer dependencies. */ async function buildSentryNextjsComponents(sentryOptions, useSentrySampling = false) { // Dynamic imports to keep @sentry/* as optional peer dependencies const Sentry = await import("@sentry/nextjs"); const SentryOtel = await import("@sentry/opentelemetry"); // Destructure common options to be defaulted, pass rest to Sentry.init const { dsn, environment, tracesSampleRate, tracesSampler, integrations, sendDefaultPii, enableLogs, ...restOptions } = sentryOptions; Sentry.init({ dsn: dsn ?? process.env.SENTRY_DSN, environment: environment ?? process.env.SENTRY_ENV ?? process.env.NODE_ENV, skipOpenTelemetrySetup: true, // Sentry Next.js defaults (which include distDirRewriteFramesIntegration, httpIntegration, etc...) integrations: integrations ?? [], tracesSampleRate: useSentrySampling ? (tracesSampleRate ?? 1) : 1, tracesSampler: useSentrySampling ? tracesSampler : undefined, sendDefaultPii: sendDefaultPii ?? false, enableLogs: enableLogs ?? true, // Pass through any additional options ...restOptions, }); const sentryClient = Sentry.getClient(); if (!sentryClient) { console.warn("[@ogcio/o11y-sdk-node] Unable to initialize Sentry client for Next.js. Telemetry may not work as expected."); } return { spanProcessor: new SentryOtel.SentrySpanProcessor(), sampler: (fallbackSampler) => sentryClient ? new SentryOtel.SentrySampler(sentryClient) : fallbackSampler, propagator: new SentryOtel.SentryPropagator(), contextManager: new Sentry.SentryContextManager(), validate: Sentry.validateOpenTelemetrySetup, }; }