Skip to content

ChatCompletion span exported with empty traceState, breaking W3C Trace Context propagation #2039

@thspinto

Description

@thspinto

Description

The ChatCompletion span created by the AI Gateway extproc is exported with an empty traceState, even when the incoming request carries a non-empty W3C tracestate header. All Envoy-native spans in the same trace (ingress, router egress) correctly preserve it — only the extproc-created span loses it.

Per the W3C Trace Context spec, received tracestate fields must be forwarded.

Root cause

In internal/tracing/tracer.go, StartSpanAndInjectHeaders() calls tracer.Start() which creates a new SpanContext with empty TraceState — the parent's value is not copied:

parentCtx := t.propagator.Extract(ctx, propagation.MapCarrier(headers))
newCtx, span := t.tracer.Start(parentCtx, spanName, opts...)  // TraceState lost here
t.propagator.Inject(newCtx, carrier)

Repro steps

Send a request with both W3C trace context headers:

curl -X POST http://<gateway-host>/v1/chat/completions \
  -H "traceparent: 00-ff202ab855ba97c79471312ef973f469-e859612da0706e48-01" \
  -H "tracestate: rojo=00f067aa0ba902b7,congo=t61rcWkgMzE" \
  -d '{"model": "<model>", "messages": [{"role": "user", "content": "hello"}]}'

Inspect the trace in any OTLP backend — the ChatCompletion span will have traceState: "" while all Envoy spans preserve the original value.

Environment

  • AI Gateway: v0.5.0
  • Envoy: v1.36.4
  • Envoy Gateway: v1.6.3
  • Go OTel SDK: v1.39.0
  • OTel propagator: autoprop (defaults to tracecontext,baggage)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginvestigateThis needs further investigation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions