1- import {
2- addTracingExtensions ,
3- captureException ,
4- getCurrentScope ,
5- runWithAsyncContext ,
6- startTransaction ,
7- } from '@sentry/core' ;
8- import { tracingContextFromHeaders , winterCGHeadersToDict } from '@sentry/utils' ;
1+ import { addTracingExtensions , captureException , continueTrace , runWithAsyncContext , trace } from '@sentry/core' ;
2+ import { winterCGHeadersToDict } from '@sentry/utils' ;
93
104import { isNotFoundNavigationError , isRedirectNavigationError } from '../common/nextNavigationErrorUtils' ;
115import type { ServerComponentContext } from '../common/types' ;
@@ -28,88 +22,57 @@ export function wrapServerComponentWithSentry<F extends (...args: any[]) => any>
2822 return new Proxy ( appDirComponent , {
2923 apply : ( originalFunction , thisArg , args ) => {
3024 return runWithAsyncContext ( ( ) => {
31- const currentScope = getCurrentScope ( ) ;
32- let maybePromiseResult ;
33-
3425 const completeHeadersDict : Record < string , string > = context . headers
3526 ? winterCGHeadersToDict ( context . headers )
3627 : { } ;
3728
38- const { traceparentData , dynamicSamplingContext , propagationContext } = tracingContextFromHeaders (
29+ const transactionContext = continueTrace ( {
3930 // eslint-disable-next-line deprecation/deprecation
40- context . sentryTraceHeader ?? completeHeadersDict [ 'sentry-trace' ] ,
31+ sentryTrace : context . sentryTraceHeader ?? completeHeadersDict [ 'sentry-trace' ] ,
4132 // eslint-disable-next-line deprecation/deprecation
42- context . baggageHeader ?? completeHeadersDict [ 'baggage' ] ,
43- ) ;
44- currentScope . setPropagationContext ( propagationContext ) ;
45-
46- const transaction = startTransaction ( {
47- op : 'function.nextjs' ,
48- name : `${ componentType } Server Component (${ componentRoute } )` ,
49- status : 'ok' ,
50- origin : 'auto.function.nextjs' ,
51- ...traceparentData ,
52- metadata : {
53- request : {
54- headers : completeHeadersDict ,
55- } ,
56- source : 'component' ,
57- dynamicSamplingContext : traceparentData && ! dynamicSamplingContext ? { } : dynamicSamplingContext ,
58- } ,
33+ baggage : context . baggageHeader ?? completeHeadersDict [ 'baggage' ] ,
5934 } ) ;
6035
61- currentScope . setSpan ( transaction ) ;
62-
63- const handleErrorCase = ( e : unknown ) : void => {
64- if ( isNotFoundNavigationError ( e ) ) {
65- // We don't want to report "not-found"s
66- transaction . setStatus ( 'not_found' ) ;
67- } else if ( isRedirectNavigationError ( e ) ) {
68- // We don't want to report redirects
69- } else {
70- transaction . setStatus ( 'internal_error' ) ;
71-
72- captureException ( e , {
73- mechanism : {
74- handled : false ,
36+ const res = trace (
37+ {
38+ ...transactionContext ,
39+ op : 'function.nextjs' ,
40+ name : `${ componentType } Server Component (${ componentRoute } )` ,
41+ status : 'ok' ,
42+ origin : 'auto.function.nextjs' ,
43+ metadata : {
44+ ...transactionContext . metadata ,
45+ request : {
46+ headers : completeHeadersDict ,
7547 } ,
76- } ) ;
77- }
78-
79- transaction . finish ( ) ;
80- } ;
81-
82- try {
83- maybePromiseResult = originalFunction . apply ( thisArg , args ) ;
84- } catch ( e ) {
85- handleErrorCase ( e ) ;
86- void flushQueue ( ) ;
87- throw e ;
88- }
48+ source : 'component' ,
49+ } ,
50+ } ,
51+ ( ) => originalFunction . apply ( thisArg , args ) ,
52+ ( e , span ) => {
53+ if ( isNotFoundNavigationError ( e ) ) {
54+ // We don't want to report "not-found"s
55+ span ?. setStatus ( 'not_found' ) ;
56+ } else if ( isRedirectNavigationError ( e ) ) {
57+ // We don't want to report redirects
58+ // Since `trace` will automatically set the span status to "internal_error" we need to set it back to "ok"
59+ span ?. setStatus ( 'ok' ) ;
60+ } else {
61+ span ?. setStatus ( 'internal_error' ) ;
8962
90- if ( typeof maybePromiseResult === 'object' && maybePromiseResult !== null && 'then' in maybePromiseResult ) {
91- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
92- Promise . resolve ( maybePromiseResult )
93- . then (
94- ( ) => {
95- transaction . finish ( ) ;
96- } ,
97- e => {
98- handleErrorCase ( e ) ;
99- } ,
100- )
101- . finally ( ( ) => {
102- void flushQueue ( ) ;
103- } ) ;
63+ captureException ( e , {
64+ mechanism : {
65+ handled : false ,
66+ } ,
67+ } ) ;
68+ }
69+ } ,
70+ ( ) => {
71+ void flushQueue ( ) ;
72+ } ,
73+ ) ;
10474
105- // It is very important that we return the original promise here, because Next.js attaches various properties
106- // to that promise and will throw if they are not on the returned value.
107- return maybePromiseResult ;
108- } else {
109- transaction . finish ( ) ;
110- void flushQueue ( ) ;
111- return maybePromiseResult ;
112- }
75+ return res ;
11376 } ) ;
11477 } ,
11578 } ) ;
0 commit comments