validatord: honor X-Lakehouse-Trace-Id even when Langfuse is off
Surfaced by the 2026-05-02 cross-runtime test: when a caller forwarded X-Lakehouse-Trace-Id but the langfuse middleware was a passthrough (no Langfuse env), the header was never read — Go minted a fallback id, breaking cross-daemon parent-trace linkage. The middleware only honored the header when its lf client was non-nil. With LANGFUSE_URL unset on the persistent stack, every inbound iterate request lost the parent linkage. Fix: validatord's iterate handler reads the header DIRECTLY (matches Rust's iterate.rs pattern) before falling through to the ctx value + fallback id. Now Go behavior matches Rust regardless of Langfuse configuration. Resolution order is: 1. req.TraceID (caller put it in the JSON body) 2. X-Lakehouse-Trace-Id header (read directly here) 3. context value from langfuse middleware (when configured) 4. fallback to a locally-minted time-ordered hex id Verified end-to-end: curl -H 'X-Lakehouse-Trace-Id: go-cmp-fixed' POST /v1/iterate → response.trace_id = "go-cmp-fixed" ✓ → sessions.jsonl row session_id = "go-cmp-fixed" ✓ Pre-fix (this commit's parent ran from /tmp/val-fresh3 binary): same call → trace_id minted as 18abbb5a008061b7-008061e9 (header silently ignored) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1263720497
commit
6847bbc180
@ -244,15 +244,23 @@ func (h *handlers) handleIterate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull the per-request trace id from the langfuse middleware. If
|
// Resolve the parent trace id, in priority order:
|
||||||
// the caller forwarded an upstream trace via X-Lakehouse-Trace-Id
|
// 1. req.TraceID (caller put it in the JSON body)
|
||||||
// the middleware reuses that one; otherwise it minted a fresh trace
|
// 2. X-Lakehouse-Trace-Id header (read DIRECTLY here so the path
|
||||||
// at HTTP entry. When Langfuse isn't configured at all the
|
// works even when Langfuse is off and the middleware is a
|
||||||
// middleware skips the mint, so we generate a fallback id locally —
|
// passthrough — matches Rust's iterate handler shape)
|
||||||
// session_id MUST always be populated so the JSONL log + Langfuse
|
// 3. context value set by the langfuse middleware (when Langfuse
|
||||||
// (when later configured) can correlate by id across logs.
|
// is configured)
|
||||||
// Surfaced 2026-05-02 deploy: empty session_id breaks DuckDB
|
// 4. fallback to a locally-minted time-ordered hex id
|
||||||
// joins on coordinator_sessions.jsonl ↔ replay_runs.jsonl.
|
//
|
||||||
|
// Surfaced 2026-05-02 cross-runtime test: Go was minting fallback
|
||||||
|
// even when caller forwarded the header, because middleware
|
||||||
|
// passthrough mode never read it. Reading the header here closes
|
||||||
|
// the gap and makes Go behavior match Rust regardless of
|
||||||
|
// Langfuse configuration.
|
||||||
|
if req.TraceID == "" {
|
||||||
|
req.TraceID = r.Header.Get(shared.TraceIDHeader)
|
||||||
|
}
|
||||||
if req.TraceID == "" {
|
if req.TraceID == "" {
|
||||||
req.TraceID = shared.TraceIDFromCtx(r.Context())
|
req.TraceID = shared.TraceIDFromCtx(r.Context())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user