5
5
captureException ,
6
6
getActiveSpan ,
7
7
getCapturedScopesOnSpan ,
8
+ getIsolationScope ,
8
9
getRootSpan ,
9
10
handleCallbackErrors ,
10
11
setCapturedScopesOnSpan ,
@@ -16,9 +17,8 @@ import {
16
17
import type { RouteHandlerContext } from './types' ;
17
18
18
19
import { propagationContextFromHeaders , winterCGHeadersToDict } from '@sentry/utils' ;
19
-
20
20
import { isNotFoundNavigationError , isRedirectNavigationError } from './nextNavigationErrorUtils' ;
21
- import { commonObjectToIsolationScope , commonObjectToPropagationContext } from './utils/tracingUtils' ;
21
+ import { commonObjectToIsolationScope } from './utils/tracingUtils' ;
22
22
23
23
/**
24
24
* Wraps a Next.js App Router Route handler with Sentry error and performance instrumentation.
@@ -34,80 +34,83 @@ export function wrapRouteHandlerWithSentry<F extends (...args: any[]) => any>(
34
34
35
35
return new Proxy ( routeHandler , {
36
36
apply : async ( originalFunction , thisArg , args ) => {
37
- const isolationScope = commonObjectToIsolationScope ( headers ) ;
38
-
39
- const completeHeadersDict : Record < string , string > = headers ? winterCGHeadersToDict ( headers ) : { } ;
40
-
41
- isolationScope . setSDKProcessingMetadata ( {
42
- request : {
43
- headers : completeHeadersDict ,
44
- } ,
45
- } ) ;
46
-
47
- const incomingPropagationContext = propagationContextFromHeaders (
48
- completeHeadersDict [ 'sentry-trace' ] ,
49
- completeHeadersDict [ 'baggage' ] ,
50
- ) ;
51
-
52
- const propagationContext = commonObjectToPropagationContext ( headers , incomingPropagationContext ) ;
53
-
54
37
const activeSpan = getActiveSpan ( ) ;
55
38
const rootSpan = activeSpan ? getRootSpan ( activeSpan ) : undefined ;
56
- if ( rootSpan ) {
39
+
40
+ let edgeRuntimeIsolationScopeOverride : Scope | undefined ;
41
+ if ( rootSpan && process . env . NEXT_RUNTIME === 'edge' ) {
42
+ const isolationScope = commonObjectToIsolationScope ( headers ) ;
57
43
const { scope } = getCapturedScopesOnSpan ( rootSpan ) ;
58
44
setCapturedScopesOnSpan ( rootSpan , scope ?? new Scope ( ) , isolationScope ) ;
59
45
60
- if ( process . env . NEXT_RUNTIME === 'edge' ) {
61
- rootSpan . updateName ( ` ${ method } ${ parameterizedRoute } ` ) ;
62
- rootSpan . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SOURCE , 'route' ) ;
63
- rootSpan . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_OP , 'http.server ' ) ;
64
- }
46
+ edgeRuntimeIsolationScopeOverride = isolationScope ;
47
+
48
+ rootSpan . updateName ( ` ${ method } ${ parameterizedRoute } ` ) ;
49
+ rootSpan . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SOURCE , 'route ' ) ;
50
+ rootSpan . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_OP , 'http.server' ) ;
65
51
}
66
52
67
- return withIsolationScope ( isolationScope , ( ) => {
68
- return withScope ( async scope => {
69
- scope . setTransactionName ( `${ method } ${ parameterizedRoute } ` ) ;
70
- scope . setPropagationContext ( propagationContext ) ;
53
+ return withIsolationScope (
54
+ process . env . NEXT_RUNTIME === 'edge' ? edgeRuntimeIsolationScopeOverride : getIsolationScope ( ) ,
55
+ ( ) => {
56
+ return withScope ( async scope => {
57
+ scope . setTransactionName ( `${ method } ${ parameterizedRoute } ` ) ;
71
58
72
- const response : Response = await handleCallbackErrors (
73
- ( ) => originalFunction . apply ( thisArg , args ) ,
74
- error => {
75
- // Next.js throws errors when calling `redirect()`. We don't wanna report these.
76
- if ( isRedirectNavigationError ( error ) ) {
77
- // Don't do anything
78
- } else if ( isNotFoundNavigationError ( error ) ) {
59
+ if ( process . env . NEXT_RUNTIME === 'edge' ) {
60
+ const completeHeadersDict : Record < string , string > = headers ? winterCGHeadersToDict ( headers ) : { } ;
61
+ const incomingPropagationContext = propagationContextFromHeaders (
62
+ completeHeadersDict [ 'sentry-trace' ] ,
63
+ completeHeadersDict [ 'baggage' ] ,
64
+ ) ;
65
+ scope . setPropagationContext ( incomingPropagationContext ) ;
66
+ scope . setSDKProcessingMetadata ( {
67
+ request : {
68
+ method,
69
+ headers : completeHeadersDict ,
70
+ } ,
71
+ } ) ;
72
+ }
73
+
74
+ const response : Response = await handleCallbackErrors (
75
+ ( ) => originalFunction . apply ( thisArg , args ) ,
76
+ error => {
77
+ // Next.js throws errors when calling `redirect()`. We don't wanna report these.
78
+ if ( isRedirectNavigationError ( error ) ) {
79
+ // Don't do anything
80
+ } else if ( isNotFoundNavigationError ( error ) ) {
81
+ if ( activeSpan ) {
82
+ setHttpStatus ( activeSpan , 404 ) ;
83
+ }
84
+ if ( rootSpan ) {
85
+ setHttpStatus ( rootSpan , 404 ) ;
86
+ }
87
+ } else {
88
+ captureException ( error , {
89
+ mechanism : {
90
+ handled : false ,
91
+ } ,
92
+ } ) ;
93
+ }
94
+ } ,
95
+ ) ;
96
+
97
+ try {
98
+ if ( response . status ) {
79
99
if ( activeSpan ) {
80
- setHttpStatus ( activeSpan , 404 ) ;
100
+ setHttpStatus ( activeSpan , response . status ) ;
81
101
}
82
102
if ( rootSpan ) {
83
- setHttpStatus ( rootSpan , 404 ) ;
103
+ setHttpStatus ( rootSpan , response . status ) ;
84
104
}
85
- } else {
86
- captureException ( error , {
87
- mechanism : {
88
- handled : false ,
89
- } ,
90
- } ) ;
91
- }
92
- } ,
93
- ) ;
94
-
95
- try {
96
- if ( response . status ) {
97
- if ( activeSpan ) {
98
- setHttpStatus ( activeSpan , response . status ) ;
99
- }
100
- if ( rootSpan ) {
101
- setHttpStatus ( rootSpan , response . status ) ;
102
105
}
106
+ } catch {
107
+ // best effort - response may be undefined?
103
108
}
104
- } catch {
105
- // best effort - response may be undefined?
106
- }
107
109
108
- return response ;
109
- } ) ;
110
- } ) ;
110
+ return response ;
111
+ } ) ;
112
+ } ,
113
+ ) ;
111
114
} ,
112
115
} ) ;
113
116
}
0 commit comments