UNPKG

@sentry/nextjs

Version:
77 lines (74 loc) • 3.92 kB
import { propagation, trace, context } from '@opentelemetry/api'; import { withSentry as withSentry$1 } from '@sentry/cloudflare'; export * from '@sentry/cloudflare'; import { applySdkMetadata, GLOBAL_OBJ, extractTraceparentData, spanToJSON, getRootSpan } from '@sentry/core'; import { setOpenTelemetryContextAsyncContextStrategy, registerPrepareSpanScope } from '@sentry/opentelemetry'; import { ATTR_NEXT_SPAN_TYPE } from '../common/nextSpanAttributes.js'; import { isTunnelRouteSpan } from '../common/utils/dropMiddlewareTunnelRequests.js'; import { dropReactControlFlowErrorsEventProcessor } from '../common/utils/dropReactControlFlowErrors.js'; import { markAsyncContextOwnedByNextjsCloudflare } from '../common/utils/responseEnd.js'; import { NextSentryPropagator } from '../server/nextSentryPropagator.js'; import { prepareSafeIdGeneratorContext } from '../server/prepareSafeIdGeneratorContext.js'; import { markPrerendersOnTracerProvider, getGlobalTracerProvider } from '../server/prerenderContext.js'; import { NEXTJS_SERVER_IGNORE_SPANS, addNextjsServerSpanHooks } from '../server/serverSpanHooks.js'; import { nextjsUseCacheIntegration } from '../server/useCacheInstrumentation.js'; prepareSafeIdGeneratorContext(); class NextjsCloudflarePropagator extends NextSentryPropagator { /** @inheritDoc */ extract(ctx, carrier, getter) { const activeSpan = trace.getSpan(context.active()); const sentryTrace = getter.get(carrier, "sentry-trace"); const incoming = extractTraceparentData(Array.isArray(sentryTrace) ? sentryTrace[0] : sentryTrace); if (activeSpan && incoming?.parentSpanId && incoming.parentSpanId === spanToJSON(getRootSpan(activeSpan)).parent_span_id) { return ctx; } return super.extract(ctx, carrier, getter); } } const nextjsIntegration = () => ({ name: "Nextjs", setup: (client) => { var _a; if (client.getOptions().enableOpenTelemetrySetup) { markPrerendersOnTracerProvider(getGlobalTracerProvider()); propagation.setGlobalPropagator(new NextjsCloudflarePropagator()); } (_a = client.getOptions()).release ?? (_a.release = GLOBAL_OBJ._sentryRelease); addNextjsServerSpanHooks(client); client.addEventProcessor(dropReactControlFlowErrorsEventProcessor); registerPrepareSpanScope(client); client.on("beforeSampling", (samplingData) => { if (isTunnelRouteSpan(samplingData.spanAttributes)) { samplingData.parentSampled = false; } }); } }); const withSentry = (optionsCallback, handler) => { setOpenTelemetryContextAsyncContextStrategy(); markAsyncContextOwnedByNextjsCloudflare(); return withSentry$1((env) => { const options = { enableOpenTelemetrySetup: true, ...optionsCallback(env) }; options.ignoreSpans = [ ...options.ignoreSpans || [], ...NEXTJS_SERVER_IGNORE_SPANS, // The request spans of Next.js repeat the request span of `withSentry`. An ignored span does not become active, // so the other Next.js spans become children of the request span of `withSentry`, which then gets the route // from their `next.route` and its status from the response. { attributes: { [ATTR_NEXT_SPAN_TYPE]: "BaseServer.handleRequest" } } ]; const { tracesSampler } = options; if (tracesSampler) { options.tracesSampler = (samplingContext) => !isTunnelRouteSpan(samplingContext.attributes || {}) && tracesSampler(samplingContext); } const userIntegrations = options.integrations; options.integrations = (defaults) => { const integrations = [...defaults, nextjsIntegration(), nextjsUseCacheIntegration()]; return typeof userIntegrations === "function" ? userIntegrations(integrations) : [...integrations, ...userIntegrations || []]; }; applySdkMetadata(options, "nextjs", ["nextjs", "cloudflare"]); return options; }, handler); }; export { withSentry }; //# sourceMappingURL=index.js.map