Skip to content

Commit cd33bb0

Browse files
committed
feat(nextjs): Remove tracing from middleware wrappers
Drops the manually-created span from the middleware wrapper. On Next.js 14+ the native OTel middleware span (normalized by enhanceMiddlewareRootSpan) already produces the middleware transaction, so the wrapper only forks an isolation scope, binds it to the native root span, captures errors, and flushes. Keeps withIsolationScope + setCapturedScopesOnSpan so per-request isolation still holds and global-scope data does not leak into the middleware transaction.
1 parent 5470b91 commit cd33bb0

1 file changed

Lines changed: 21 additions & 42 deletions

File tree

packages/nextjs/src/common/wrapMiddlewareWithSentry.ts

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
import type { TransactionSource } from '@sentry/core';
21
import {
32
captureException,
43
getActiveSpan,
54
getCurrentScope,
65
getRootSpan,
76
handleCallbackErrors,
8-
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
9-
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
107
setCapturedScopesOnSpan,
11-
startSpan,
128
winterCGRequestToRequestData,
139
withIsolationScope,
1410
} from '@sentry/core';
@@ -17,7 +13,11 @@ import { isPathnameUnderSentryTunnelRoute } from '../common/utils/tunnelPathname
1713
import type { EdgeRouteHandler } from '../edge/types';
1814

1915
/**
20-
* Wraps Next.js middleware with Sentry error and performance instrumentation.
16+
* Wraps Next.js middleware with Sentry error instrumentation.
17+
*
18+
* The middleware transaction itself is created by Next.js' native OpenTelemetry instrumentation
19+
* (the `Middleware.execute` span, normalized by `enhanceMiddlewareRootSpan`), so this wrapper no
20+
* longer starts its own span. It only forks an isolation scope, captures errors, and flushes.
2121
*
2222
* @param middleware The middleware handler.
2323
* @returns a wrapped middleware handler.
@@ -32,6 +32,7 @@ export function wrapMiddlewareWithSentry<H extends EdgeRouteHandler>(
3232
? (globalThis as Record<string, unknown>)._sentryRewritesTunnelPath
3333
: undefined;
3434

35+
// TODO: This can never work with Turbopack, need to remove it for consistency between builds.
3536
if (tunnelRoute && typeof tunnelRoute === 'string') {
3637
const req: unknown = args[0];
3738
// Check if the current request matches the tunnel route
@@ -52,65 +53,43 @@ export function wrapMiddlewareWithSentry<H extends EdgeRouteHandler>(
5253
}
5354
}
5455
}
56+
5557
// TODO: We still should add central isolation scope creation for when our build-time instrumentation does not work anymore with turbopack.
5658
return withIsolationScope(isolationScope => {
5759
const req: unknown = args[0];
5860
const currentScope = getCurrentScope();
5961

60-
let spanName: string;
61-
let spanSource: TransactionSource;
62-
6362
if (req instanceof Request) {
6463
isolationScope.setSDKProcessingMetadata({
6564
normalizedRequest: winterCGRequestToRequestData(req),
6665
});
67-
spanName = `middleware ${req.method}`;
68-
spanSource = 'url';
66+
currentScope.setTransactionName(`middleware ${req.method}`);
6967
} else {
70-
spanName = 'middleware';
71-
spanSource = 'component';
68+
currentScope.setTransactionName('middleware');
7269
}
7370

74-
currentScope.setTransactionName(spanName);
75-
7671
const activeSpan = getActiveSpan();
77-
7872
if (activeSpan) {
79-
// If there is an active span, it likely means that the automatic Next.js OTEL instrumentation worked and we can
80-
// rely on that for parameterization.
81-
spanName = 'middleware';
82-
spanSource = 'component';
83-
73+
// If there is an active span, the native Next.js OTEL instrumentation created the middleware root span.
74+
// Bind our forked scopes to it so the transaction picks up the isolation scope instead of the global one.
8475
const rootSpan = getRootSpan(activeSpan);
8576
if (rootSpan) {
8677
setCapturedScopesOnSpan(rootSpan, currentScope, isolationScope);
8778
}
8879
}
8980

90-
return startSpan(
91-
{
92-
name: spanName,
93-
op: 'http.server.middleware',
94-
attributes: {
95-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: spanSource,
96-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs.wrap_middleware',
97-
},
81+
return handleCallbackErrors(
82+
() => wrappingTarget.apply(thisArg, args),
83+
error => {
84+
captureException(error, {
85+
mechanism: {
86+
type: 'auto.function.nextjs.wrap_middleware',
87+
handled: false,
88+
},
89+
});
9890
},
9991
() => {
100-
return handleCallbackErrors(
101-
() => wrappingTarget.apply(thisArg, args),
102-
error => {
103-
captureException(error, {
104-
mechanism: {
105-
type: 'auto.function.nextjs.wrap_middleware',
106-
handled: false,
107-
},
108-
});
109-
},
110-
() => {
111-
waitUntil(flushSafelyWithTimeout());
112-
},
113-
);
92+
waitUntil(flushSafelyWithTimeout());
11493
},
11594
);
11695
});

0 commit comments

Comments
 (0)