diff --git a/packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts b/packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts index fe205f23a0cf..52b6bbf7bb17 100644 --- a/packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts +++ b/packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts @@ -10,7 +10,6 @@ import { handleCallbackErrors, setHttpStatus, startSpan, - withIsolationScope, } from '@sentry/core'; import type { Span } from '@sentry/types'; import { winterCGHeadersToDict } from '@sentry/utils'; @@ -22,10 +21,7 @@ import { withIsolationScopeOrReuseFromRootSpan } from './utils/withIsolationScop /** As our own HTTP integration is disabled (src/server/index.ts) the rootSpan comes from Next.js. * In case there is not root span, we start a new span. */ -function startOrUpdateSpan( - spanName: string, - handleResponseErrors: (rootSpan: Span) => Promise, -): Promise { +function startOrUpdateSpan(spanName: string, cb: (rootSpan: Span) => Promise): Promise { const activeSpan = getActiveSpan(); const rootSpan = activeSpan && getRootSpan(activeSpan); @@ -35,7 +31,7 @@ function startOrUpdateSpan( rootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'http.server'); rootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.function.nextjs'); - return handleResponseErrors(rootSpan); + return cb(rootSpan); } else { return startSpan( { @@ -48,7 +44,7 @@ function startOrUpdateSpan( }, }, (span: Span) => { - return handleResponseErrors(span); + return cb(span); }, ); } @@ -68,7 +64,7 @@ export function wrapRouteHandlerWithSentry any>( return new Proxy(routeHandler, { apply: (originalFunction, thisArg, args) => { - return withIsolationScope(async isolationScope => { + return withIsolationScopeOrReuseFromRootSpan(async isolationScope => { isolationScope.setSDKProcessingMetadata({ request: { headers: headers ? winterCGHeadersToDict(headers) : undefined, diff --git a/packages/nextjs/src/server/requestIsolationScopeIntegration.ts b/packages/nextjs/src/server/requestIsolationScopeIntegration.ts index 44a118419025..ee6e205caebc 100644 --- a/packages/nextjs/src/server/requestIsolationScopeIntegration.ts +++ b/packages/nextjs/src/server/requestIsolationScopeIntegration.ts @@ -1,6 +1,13 @@ import { SpanKind } from '@opentelemetry/api'; -import { defineIntegration, spanToJSON } from '@sentry/core'; -import { getSpanKind, getSpanScopes } from '@sentry/opentelemetry'; +import { + defineIntegration, + getCapturedScopesOnSpan, + getCurrentScope, + getIsolationScope, + setCapturedScopesOnSpan, + spanToJSON, +} from '@sentry/core'; +import { getSpanKind } from '@sentry/opentelemetry'; /** * This integration is responsible for creating isolation scopes for incoming Http requests. @@ -15,13 +22,17 @@ export const requestIsolationScopeIntegration = defineIntegration(() => { setup(client) { client.on('spanStart', span => { const spanJson = spanToJSON(span); + const data = spanJson.data || {}; // The following check is a heuristic to determine whether the started span is a span that tracks an incoming HTTP request - if (getSpanKind(span) === SpanKind.SERVER && spanJson.data && 'http.method' in spanJson.data) { - const scopes = getSpanScopes(span); - if (scopes) { - scopes.isolationScope = scopes.isolationScope.clone(); - } + if ((getSpanKind(span) === SpanKind.SERVER && data['http.method']) || data['next.route']) { + const scopes = getCapturedScopesOnSpan(span); + + // Update the isolation scope, isolate this request + const isolationScope = (scopes.isolationScope || getIsolationScope()).clone(); + const scope = scopes.scope || getCurrentScope(); + + setCapturedScopesOnSpan(span, scope, isolationScope); } }); },