Coffee journaling on ATProto (alpha) alpha.arabica.social
coffee
17
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: improved trace propagation and naming for frontend requests

authored by

Patrick Dewey and committed by tangled.org 4204d27e 5dd7fe2b

+32 -1
+18 -1
internal/routing/routing.go
··· 10 10 11 11 "github.com/rs/zerolog" 12 12 "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" 13 + "go.opentelemetry.io/otel/attribute" 14 + "go.opentelemetry.io/otel/trace" 13 15 ) 14 16 15 17 // Config holds the configuration needed for setting up routes ··· 170 172 // 5. Apply logging middleware 171 173 handler = middleware.LoggingMiddleware(cfg.Logger)(handler) 172 174 173 - // 6. Apply OpenTelemetry HTTP instrumentation (outermost - wraps everything) 175 + // 6. Enrich trace spans with client page context (runs inside otelhttp span) 176 + handler = pageContextMiddleware(handler) 177 + 178 + // 7. Apply OpenTelemetry HTTP instrumentation (outermost - wraps everything) 174 179 handler = otelhttp.NewHandler(handler, "arabica", 175 180 otelhttp.WithFilter(func(r *http.Request) bool { 176 181 return !strings.HasPrefix(r.URL.Path, "/static/") && r.URL.Path != "/favicon.ico" ··· 182 187 183 188 return handler 184 189 } 190 + 191 + // pageContextMiddleware reads the X-Page-Context header (set by client-side JS) 192 + // and adds it as a span attribute so traces show which page triggered the request. 193 + func pageContextMiddleware(next http.Handler) http.Handler { 194 + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 195 + if page := r.Header.Get("X-Page-Context"); page != "" { 196 + span := trace.SpanFromContext(r.Context()) 197 + span.SetAttributes(attribute.String("http.page_context", page)) 198 + } 199 + next.ServeHTTP(w, r) 200 + }) 201 + }
+3
internal/web/components/layout.templ
··· 258 258 <script src="/static/js/data-cache.js?v=0.2.0"></script> 259 259 } 260 260 <script src="/static/js/sw-register.js?v=0.2.0"></script> 261 + if tp := traceParentFromContext(ctx); tp != "" { 262 + <meta name="traceparent" content={ tp }/> 263 + } 261 264 </head> 262 265 <body 263 266 class="bg-brown-50 min-h-full flex flex-col"
+11
static/js/data-cache.js
··· 108 108 * Fetch fresh data from the API 109 109 */ 110 110 async function fetchFreshData() { 111 + const headers = { 112 + "X-Page-Context": window.location.pathname, 113 + }; 114 + 115 + // Propagate W3C traceparent from server-rendered meta tag 116 + const tp = document.querySelector('meta[name="traceparent"]')?.content; 117 + if (tp) { 118 + headers["traceparent"] = tp; 119 + } 120 + 111 121 const response = await fetch("/api/data", { 112 122 credentials: "same-origin", 123 + headers, 113 124 }); 114 125 115 126 if (!response.ok) {