Skip to content

Commit 976afe2

Browse files
authored
fix(nextjs): Fix conditional root span handling for route handlers (#11608)
This should make our checks more robust.
1 parent 1db5b68 commit 976afe2

File tree

1 file changed

+28
-18
lines changed

1 file changed

+28
-18
lines changed

packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
getRootSpan,
99
handleCallbackErrors,
1010
setHttpStatus,
11+
spanToJSON,
1112
startSpan,
1213
} from '@sentry/core';
1314
import type { Span } from '@sentry/types';
@@ -24,32 +25,41 @@ function startOrUpdateSpan(spanName: string, cb: (rootSpan: Span) => Promise<Res
2425
const activeSpan = getActiveSpan();
2526
const rootSpan = activeSpan && getRootSpan(activeSpan);
2627

27-
if (rootSpan) {
28-
rootSpan.updateName(spanName);
29-
rootSpan.setAttributes({
30-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
31-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',
32-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs',
33-
});
28+
// We have different possible scenarios here:
29+
// 1. If we have no root span, we just create a new span
30+
// 2. We have a root span that that we want to update here
31+
// 3. We have a root span that was already updated (e.g. if this is a nested call)
3432

35-
return cb(rootSpan);
36-
} else {
33+
const attributes = {
34+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
35+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',
36+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs',
37+
} as const;
38+
39+
if (!rootSpan) {
3740
return startSpan(
3841
{
39-
op: 'http.server',
4042
name: spanName,
4143
forceTransaction: true,
42-
attributes: {
43-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
44-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',
45-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs',
46-
},
47-
},
48-
(span: Span) => {
49-
return cb(span);
44+
attributes,
5045
},
46+
cb,
5147
);
5248
}
49+
50+
// If `op` is set, we assume this was already processed before
51+
// Probably this is a nested call, no need to update anything anymore
52+
// OR, if we don't have next.span_type, we don't know where this comes from and don't want to mess with it
53+
const existingAttributes = spanToJSON(rootSpan).data || {};
54+
if (existingAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || !existingAttributes['next.span_type']) {
55+
return cb(rootSpan);
56+
}
57+
58+
// Finally, we want to update the root span, as the ones generated by next are often not good enough for us
59+
rootSpan.updateName(spanName);
60+
rootSpan.setAttributes(attributes);
61+
62+
return cb(rootSpan);
5363
}
5464

5565
/**

0 commit comments

Comments
 (0)