@@ -4,11 +4,8 @@ import {
4
4
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ,
5
5
SPAN_STATUS_ERROR ,
6
6
captureException ,
7
- getActiveSpan ,
8
- getRootSpan ,
9
7
handleCallbackErrors ,
10
8
setHttpStatus ,
11
- spanToJSON ,
12
9
startSpan ,
13
10
} from '@sentry/core' ;
14
11
import type { Span } from '@sentry/types' ;
@@ -19,49 +16,6 @@ import { platformSupportsStreaming } from './utils/platformSupportsStreaming';
19
16
import { flushQueue } from './utils/responseEnd' ;
20
17
import { withIsolationScopeOrReuseFromRootSpan } from './utils/withIsolationScopeOrReuseFromRootSpan' ;
21
18
22
- /** As our own HTTP integration is disabled (src/server/index.ts) the rootSpan comes from Next.js.
23
- * In case there is no root span, we start a new span. */
24
- function startOrUpdateSpan ( spanName : string , cb : ( rootSpan : Span ) => Promise < Response > ) : Promise < Response > {
25
- const activeSpan = getActiveSpan ( ) ;
26
- const rootSpan = activeSpan && getRootSpan ( activeSpan ) ;
27
-
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)
32
-
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 ) {
40
- return startSpan (
41
- {
42
- name : spanName ,
43
- forceTransaction : true ,
44
- attributes,
45
- } ,
46
- cb ,
47
- ) ;
48
- }
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 ) ;
63
- }
64
-
65
19
/**
66
20
* Wraps a Next.js route handler with performance and error instrumentation.
67
21
*/
@@ -82,35 +36,46 @@ export function wrapRouteHandlerWithSentry<F extends (...args: any[]) => any>(
82
36
} ) ;
83
37
84
38
try {
85
- return await startOrUpdateSpan ( `${ method } ${ parameterizedRoute } ` , async ( rootSpan : Span ) => {
86
- const response : Response = await handleCallbackErrors (
87
- ( ) => originalFunction . apply ( thisArg , args ) ,
88
- error => {
89
- // Next.js throws errors when calling `redirect()`. We don't wanna report these.
90
- if ( isRedirectNavigationError ( error ) ) {
91
- // Don't do anything
92
- } else if ( isNotFoundNavigationError ( error ) && rootSpan ) {
93
- rootSpan . setStatus ( { code : SPAN_STATUS_ERROR , message : 'not_found' } ) ;
94
- } else {
95
- captureException ( error , {
96
- mechanism : {
97
- handled : false ,
98
- } ,
99
- } ) ;
100
- }
39
+ return await startSpan (
40
+ {
41
+ name : `${ method } ${ parameterizedRoute } ` ,
42
+ forceTransaction : true ,
43
+ attributes : {
44
+ [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : 'route' ,
45
+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'http.server' ,
46
+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.function.nextjs' ,
101
47
} ,
102
- ) ;
48
+ } ,
49
+ async ( span : Span ) => {
50
+ const response : Response = await handleCallbackErrors (
51
+ ( ) => originalFunction . apply ( thisArg , args ) ,
52
+ error => {
53
+ // Next.js throws errors when calling `redirect()`. We don't wanna report these.
54
+ if ( isRedirectNavigationError ( error ) ) {
55
+ // Don't do anything
56
+ } else if ( isNotFoundNavigationError ( error ) ) {
57
+ span . setStatus ( { code : SPAN_STATUS_ERROR , message : 'not_found' } ) ;
58
+ } else {
59
+ captureException ( error , {
60
+ mechanism : {
61
+ handled : false ,
62
+ } ,
63
+ } ) ;
64
+ }
65
+ } ,
66
+ ) ;
103
67
104
- try {
105
- if ( rootSpan && response . status ) {
106
- setHttpStatus ( rootSpan , response . status ) ;
68
+ try {
69
+ if ( response . status ) {
70
+ setHttpStatus ( span , response . status ) ;
71
+ }
72
+ } catch {
73
+ // best effort - response may be undefined?
107
74
}
108
- } catch {
109
- // best effort - response may be undefined?
110
- }
111
75
112
- return response ;
113
- } ) ;
76
+ return response ;
77
+ } ,
78
+ ) ;
114
79
} finally {
115
80
if ( ! platformSupportsStreaming ( ) || process . env . NEXT_RUNTIME === 'edge' ) {
116
81
// 1. Edge transport requires manual flushing
0 commit comments