From 89e7e25b6059d099f656c55538d8d6e1ca5e122b Mon Sep 17 00:00:00 2001 From: Cedric Ziel Date: Tue, 19 Nov 2024 09:01:58 +0100 Subject: [PATCH] Backend: Inject server-timing header to match initial loads with client-side telemetry (#94978) feat: inject server-timing header to match initial loads with client-side telemetry Faro Web SDK can read the server-timing info and correlate the initial request with the client side telemetry gather from navigation timings. --- pkg/infra/tracing/tracing.go | 9 +++++++++ pkg/middleware/request_tracing.go | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/pkg/infra/tracing/tracing.go b/pkg/infra/tracing/tracing.go index 4c6bd6545a3..5f028c6ce80 100644 --- a/pkg/infra/tracing/tracing.go +++ b/pkg/infra/tracing/tracing.go @@ -381,6 +381,15 @@ func TraceIDFromContext(ctx context.Context, requireSampled bool) string { return spanCtx.TraceID().String() } +func ServerTimingForSpan(span trace.Span) string { + spanCtx := span.SpanContext() + if !spanCtx.HasTraceID() || !spanCtx.IsValid() { + return "" + } + + return fmt.Sprintf("00-%s-%s-01", spanCtx.TraceID().String(), spanCtx.SpanID().String()) +} + // Error sets the status to error and record the error as an exception in the provided span. func Error(span trace.Span, err error) error { attr := []attribute.KeyValue{} diff --git a/pkg/middleware/request_tracing.go b/pkg/middleware/request_tracing.go index 2985fe0ad60..2f492a697f9 100644 --- a/pkg/middleware/request_tracing.go +++ b/pkg/middleware/request_tracing.go @@ -94,6 +94,14 @@ func RequestTracing(tracer tracing.Tracer) web.Middleware { ), trace.WithSpanKind(trace.SpanKindServer)) defer span.End() + // inject local root span context into the response via server-timing header + // we're doing it this early so that we can capture the root span context + // which is not available later-on. + serverTimingValue := tracing.ServerTimingForSpan(span) + if serverTimingValue != "" { + w.Header().Set("server-timing", fmt.Sprintf("traceparent;desc=\"%s\"", serverTimingValue)) + } + req = req.WithContext(ctx) // Ensure the response writer's status can be captured.