Keep a hop's parent after rewriting its header

traceOf read the caller's ids as slices of a view over the header
buffer, then rewrote that buffer in place: every shipped span named
itself as its parent, and once the connection served its next request
the span carried that request's trace id.

Claude-Session: https://claude.ai/code/session_01HuMDfgFssPUptYUzgZ6Cp8
This commit is contained in:
2026-09-24 14:43:20 -07:00
parent 55db4f138b
commit f2a543133e
2 changed files with 22 additions and 1 deletions
+5 -1
View File
@@ -653,7 +653,11 @@ type trace struct {
// request is the one that has to begin it.
func traceOf(c *Ctx) trace {
t := trace{}
if id, parent, ok := parseTrace(c.fc.Get(HeaderTrace)); ok {
// CLONED, because the ids are slices of it and it is a view over the header
// buffer: the Set below rewrites that buffer in place, which would turn the
// parent into this hop's own span, and the connection's next request rewrites
// it again before the span ships.
if id, parent, ok := parseTrace(strings.Clone(c.fc.Get(HeaderTrace))); ok {
t.trace, t.parent = id, parent
} else {
t.trace = mint(16)
+17
View File
@@ -54,3 +54,20 @@ func TestTraceparentHook(t *testing.T) {
t.Fatalf("hook answer: sent %q, want %q over the request's", overridden, own)
}
}
// The span a hop ships names its caller as parent and its own id as itself, even
// after the hop has rewritten the header the caller's ids were read from, and
// after the connection's next request has overwritten it.
func TestTraceOfKeepsTheCallersIDs(t *testing.T) {
const (
caller = "4bf92f3577b34da6a3ce929d0e0e4736"
parent = "00f067aa0ba902b7"
)
c := New(Config{AppName: "front", DisableStartupMessage: true}).TestCtx("GET", "/ask")
c.fc.Request().Header.Set(HeaderTrace, "00-"+caller+"-"+parent+"-01")
tr := traceOf(c)
c.fc.Request().Header.Set(HeaderTrace, "00-ffffffffffffffffffffffffffffffff-ffffffffffffffff-01")
if tr.trace != caller || tr.parent != parent || tr.span == parent {
t.Fatalf("trace = %+v, want trace %s parent %s and a span of its own", tr, caller, parent)
}
}