@@ -227,13 +227,15 @@ function makeWrappedDataFunction(
227227 build ?: ServerBuild ,
228228) : DataFunction {
229229 return async function ( this : unknown , args : DataFunctionArgs ) : Promise < Response | AppData > {
230+ let res : Response | AppData ;
231+
230232 if ( instrumentTracing ) {
231233 // Update span name for Cloudflare Workers/Hydrogen environments
232234 if ( build ) {
233235 updateSpanWithRoute ( args , build ) ;
234236 }
235237
236- return startSpan (
238+ res = await startSpan (
237239 {
238240 op : `function.remix.${ name } ` ,
239241 name : id ,
@@ -248,8 +250,24 @@ function makeWrappedDataFunction(
248250 } ,
249251 ) ;
250252 } else {
251- return errorHandleDataFunction . call ( this , origFn , name , args ) ;
253+ res = await errorHandleDataFunction . call ( this , origFn , name , args ) ;
252254 }
255+
256+ // Inject Server-Timing header for redirect responses.
257+ // Redirects bypass makeWrappedDocumentRequestFunction, so we inject here using the active OTel span.
258+ if ( isResponse ( res ) && isRedirectResponse ( res ) && ! res . headers . has ( 'Server-Timing' ) ) {
259+ const activeSpan = getActiveSpan ( ) ;
260+ const rootSpan = activeSpan && getRootSpan ( activeSpan ) ;
261+ if ( rootSpan ) {
262+ const serverTimingHeader = generateSentryServerTimingHeader ( { span : rootSpan } ) ;
263+ if ( serverTimingHeader ) {
264+ DEBUG_BUILD && debug . log ( 'Injecting Server-Timing header for redirect response' ) ;
265+ return injectServerTimingHeaderValue ( res , serverTimingHeader ) ;
266+ }
267+ }
268+ }
269+
270+ return res ;
253271 } ;
254272}
255273
0 commit comments