1- import  {  Scope ,  getActiveSpan ,  getCapturedScopesOnSpan ,  getRootSpan ,  setCapturedScopesOnSpan  }  from  '@sentry/core' ; 
1+ import  { 
2+   Scope , 
3+   captureException , 
4+   getActiveSpan , 
5+   getCapturedScopesOnSpan , 
6+   getRootSpan , 
7+   handleCallbackErrors , 
8+   setCapturedScopesOnSpan , 
9+   withIsolationScope , 
10+   withScope , 
11+ }  from  '@sentry/core' ; 
212
313import  type  {  RouteHandlerContext  }  from  './types' ; 
414
5- import  {  commonObjectToIsolationScope  }  from  './utils/tracingUtils' ; 
15+ import  {  propagationContextFromHeaders ,  winterCGHeadersToDict  }  from  '@sentry/utils' ; 
16+ 
17+ import  {  isRedirectNavigationError  }  from  './nextNavigationErrorUtils' ; 
18+ import  {  commonObjectToIsolationScope ,  commonObjectToPropagationContext  }  from  './utils/tracingUtils' ; 
619
720/** 
821 * Wraps a Next.js App Router Route handler with Sentry error and performance instrumentation. 
@@ -14,24 +27,56 @@ export function wrapRouteHandlerWithSentry<F extends (...args: any[]) => any>(
1427  routeHandler : F , 
1528  context : RouteHandlerContext , 
1629) : ( ...args : Parameters < F > )  =>  ReturnType < F >  extends  Promise < unknown >  ? ReturnType < F >  : Promise < ReturnType < F > >  { 
17-   const  {  headers }  =  context ; 
30+   const  {  method ,  parameterizedRoute ,   headers }  =  context ; 
1831
1932  return  new  Proxy ( routeHandler ,  { 
20-     apply : ( originalFunction ,  thisArg ,  args )  =>  { 
33+     apply : async   ( originalFunction ,  thisArg ,  args )  =>  { 
2134      const  isolationScope  =  commonObjectToIsolationScope ( headers ) ; 
2235
36+       const  completeHeadersDict : Record < string ,  string >  =  headers  ? winterCGHeadersToDict ( headers )  : { } ; 
37+ 
38+       isolationScope . setSDKProcessingMetadata ( { 
39+         request : { 
40+           headers : completeHeadersDict , 
41+         } , 
42+       } ) ; 
43+ 
44+       const  incomingPropagationContext  =  propagationContextFromHeaders ( 
45+         completeHeadersDict [ 'sentry-trace' ] , 
46+         completeHeadersDict [ 'baggage' ] , 
47+       ) ; 
48+ 
49+       const  propagationContext  =  commonObjectToPropagationContext ( headers ,  incomingPropagationContext ) ; 
50+ 
2351      const  activeSpan  =  getActiveSpan ( ) ; 
2452      if  ( activeSpan )  { 
2553        const  rootSpan  =  getRootSpan ( activeSpan ) ; 
54+         rootSpan . setAttribute ( 'sentry.route_handler' ,  true ) ; 
2655        const  {  scope }  =  getCapturedScopesOnSpan ( rootSpan ) ; 
2756        setCapturedScopesOnSpan ( rootSpan ,  scope  ??  new  Scope ( ) ,  isolationScope ) ; 
28- 
29-         // We mark the root span as an app route handler span so we can allow-list it in our span processor 
30-         // that would normally filter out all Next.js transactions/spans 
31-         rootSpan . setAttribute ( 'sentry.route_handler' ,  true ) ; 
3257      } 
3358
34-       return  originalFunction . apply ( thisArg ,  args ) ; 
59+       return  withIsolationScope ( isolationScope ,  ( )  =>  { 
60+         return  withScope ( scope  =>  { 
61+           scope . setTransactionName ( `${ method }   ${ parameterizedRoute }  ` ) ; 
62+           scope . setPropagationContext ( propagationContext ) ; 
63+           return  handleCallbackErrors ( 
64+             ( )  =>  originalFunction . apply ( thisArg ,  args ) , 
65+             error  =>  { 
66+               // Next.js throws errors when calling `redirect()`. We don't wanna report these. 
67+               if  ( isRedirectNavigationError ( error ) )  { 
68+                 // Don't do anything 
69+               }  else  { 
70+                 captureException ( error ,  { 
71+                   mechanism : { 
72+                     handled : false , 
73+                   } , 
74+                 } ) ; 
75+               } 
76+             } , 
77+           ) ; 
78+         } ) ; 
79+       } ) ; 
3580    } , 
3681  } ) ; 
3782} 
0 commit comments