55 runWithAsyncContext ,
66 startTransaction ,
77} from '@sentry/core' ;
8- import type { Transaction } from '@sentry/types' ;
8+ import type { Span , Transaction } from '@sentry/types' ;
99import { baggageHeaderToDynamicSamplingContext , extractTraceparentData } from '@sentry/utils' ;
1010import type { IncomingMessage , ServerResponse } from 'http' ;
1111
@@ -82,7 +82,8 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
8282 return async function ( this : unknown , ...args : Parameters < F > ) : Promise < ReturnType < F > > {
8383 return runWithAsyncContext ( async ( ) => {
8484 const hub = getCurrentHub ( ) ;
85- let requestTransaction : Transaction | undefined = getTransactionFromRequest ( req ) ;
85+ const scope = hub . getScope ( ) ;
86+ const previousSpan : Span | undefined = getTransactionFromRequest ( req ) ?? scope . getSpan ( ) ;
8687 let dataFetcherSpan ;
8788
8889 const sentryTraceHeader = req . headers [ 'sentry-trace' ] ;
@@ -93,7 +94,8 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
9394 const dynamicSamplingContext = baggageHeaderToDynamicSamplingContext ( rawBaggageString ) ;
9495
9596 if ( platformSupportsStreaming ( ) ) {
96- if ( requestTransaction === undefined ) {
97+ let spanToContinue : Span ;
98+ if ( previousSpan === undefined ) {
9799 const newTransaction = startTransaction (
98100 {
99101 op : 'http.server' ,
@@ -109,8 +111,6 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
109111 { request : req } ,
110112 ) ;
111113
112- requestTransaction = newTransaction ;
113-
114114 if ( platformSupportsStreaming ( ) ) {
115115 // On platforms that don't support streaming, doing things after res.end() is unreliable.
116116 autoEndTransactionOnResponseEnd ( newTransaction , res ) ;
@@ -119,9 +119,12 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
119119 // Link the transaction and the request together, so that when we would normally only have access to one, it's
120120 // still possible to grab the other.
121121 setTransactionOnRequest ( newTransaction , req ) ;
122+ spanToContinue = newTransaction ;
123+ } else {
124+ spanToContinue = previousSpan ;
122125 }
123126
124- dataFetcherSpan = requestTransaction . startChild ( {
127+ dataFetcherSpan = spanToContinue . startChild ( {
125128 op : 'function.nextjs' ,
126129 description : `${ options . dataFetchingMethodName } (${ options . dataFetcherRouteName } )` ,
127130 status : 'ok' ,
@@ -140,22 +143,20 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
140143 } ) ;
141144 }
142145
143- const currentScope = hub . getScope ( ) ;
144- if ( currentScope ) {
145- currentScope . setSpan ( dataFetcherSpan ) ;
146- currentScope . setSDKProcessingMetadata ( { request : req } ) ;
147- }
146+ scope . setSpan ( dataFetcherSpan ) ;
147+ scope . setSDKProcessingMetadata ( { request : req } ) ;
148148
149149 try {
150150 return await origDataFetcher . apply ( this , args ) ;
151151 } catch ( e ) {
152152 // Since we finish the span before the error can bubble up and trigger the handlers in `registerErrorInstrumentation`
153153 // that set the transaction status, we need to manually set the status of the span & transaction
154154 dataFetcherSpan . setStatus ( 'internal_error' ) ;
155- requestTransaction ?. setStatus ( 'internal_error' ) ;
155+ previousSpan ?. setStatus ( 'internal_error' ) ;
156156 throw e ;
157157 } finally {
158158 dataFetcherSpan . finish ( ) ;
159+ scope . setSpan ( previousSpan ) ;
159160 if ( ! platformSupportsStreaming ( ) ) {
160161 await flushQueue ( ) ;
161162 }
0 commit comments