diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index d72295f973a8..b52972de762b 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -35,12 +35,14 @@ "access": "public" }, "dependencies": { + "@opentelemetry/api": "1.7.0", "@rollup/plugin-commonjs": "24.0.0", "@sentry/core": "8.0.0-alpha.5", "@sentry/node": "8.0.0-alpha.5", "@sentry/react": "8.0.0-alpha.5", "@sentry/types": "8.0.0-alpha.5", "@sentry/utils": "8.0.0-alpha.5", + "@sentry/opentelemetry": "8.0.0-alpha.5", "@sentry/vercel-edge": "8.0.0-alpha.5", "@sentry/webpack-plugin": "2.16.0", "chalk": "3.0.0", diff --git a/packages/nextjs/src/server/requestIsolationScopeIntegration.ts b/packages/nextjs/src/server/requestIsolationScopeIntegration.ts new file mode 100644 index 000000000000..44a118419025 --- /dev/null +++ b/packages/nextjs/src/server/requestIsolationScopeIntegration.ts @@ -0,0 +1,29 @@ +import { SpanKind } from '@opentelemetry/api'; +import { defineIntegration, spanToJSON } from '@sentry/core'; +import { getSpanKind, getSpanScopes } from '@sentry/opentelemetry'; + +/** + * This integration is responsible for creating isolation scopes for incoming Http requests. + * We do so by waiting for http spans to be created and then forking the isolation scope. + * + * Normally the isolation scopes would be created by our Http instrumentation, however Next.js brings it's own Http + * instrumentation so we had to disable ours. + */ +export const requestIsolationScopeIntegration = defineIntegration(() => { + return { + name: 'RequestIsolationScope', + setup(client) { + client.on('spanStart', span => { + const spanJson = spanToJSON(span); + + // 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(); + } + } + }); + }, + }; +});