Skip to content

Commit fa61b3c

Browse files
committed
Inject Server-Timing header on redirect responses
1 parent 2d9f096 commit fa61b3c

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

packages/remix/src/server/instrumentServer.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)