@sentry/nextjs
Version:
Official Sentry SDK for Next.js
77 lines (74 loc) • 3.92 kB
JavaScript
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