Context
Request tracing (fastrace → OTLP, OPENINFER_TRACE_OTLP_ENDPOINT) emits request → queue/prefill/decode spans per request. When openinfer sits behind an OTel-speaking proxy (e.g. vllm-project/router with --enable-trace), we want one trace for client → router → openinfer → prefill → decode.
The last hop was broken: the pinned vllm-server (Rust frontend, git dep) forwards X-Request-Id but drops traceparent, so the bridge always started a fresh trace (SpanContext::random()). Upstream Python vLLM extracts traceparent/tracestate into EngineCoreRequest.trace_headers; the Rust server never populated that field. Verified the gap exists on upstream main, not just our pin.
Current state (local MVP, landed in-tree)
openinfer-vllm-frontend/src/trace_context.rs stashes the incoming traceparent at the axum boundary keyed by X-Request-Id (injected when absent); the bridge pops it via external_req_id lookup (tolerating vllm-server's cmpl-/chatcmpl- prefixes) and uses it as the parent of the request root span. Verified e2e on RTX 5070 Ti: single Tempo trace spans router http_request → router http_client_request → openinfer request → queue/prefill/decode, for both /v1/completions and /v1/chat/completions, with and without a client-supplied traceparent.
The X-Request-Id stash+correlation is a workaround and should not be permanent.
Upstream fix
Migration (once the upstream PR merges and we bump the vllm pin)
- Bump the
vllm-server/vllm-engine-core-client pin to a rev containing the PR.
bridge.rs: decode the parent from EngineCoreRequest.trace_headers["traceparent"] (SpanContext::decode_w3c_traceparent) instead of TraceContextStash lookup. The request-span parent-resolution code stays; only the source changes.
- Delete
openinfer-vllm-frontend/src/trace_context.rs and its wiring in lib.rs (the external_req_id correlation and prefix-stripping go away entirely).
Side observation (router upstream)
vllm-router's http_client_request span occasionally shows a ~5s duration while its server span is ~300ms (observed on the non-streaming path); likely a span-lifetime bug in the router's instrumentation. Consider reporting to vllm-project/router separately.
Ref: docs/subsystems/tracing/e2e-router-tracing.md
Context
Request tracing (fastrace → OTLP,
OPENINFER_TRACE_OTLP_ENDPOINT) emitsrequest → queue/prefill/decodespans per request. When openinfer sits behind an OTel-speaking proxy (e.g. vllm-project/router with--enable-trace), we want one trace forclient → router → openinfer → prefill → decode.The last hop was broken: the pinned vllm-server (Rust frontend, git dep) forwards
X-Request-Idbut dropstraceparent, so the bridge always started a fresh trace (SpanContext::random()). Upstream Python vLLM extractstraceparent/tracestateintoEngineCoreRequest.trace_headers; the Rust server never populated that field. Verified the gap exists on upstream main, not just our pin.Current state (local MVP, landed in-tree)
openinfer-vllm-frontend/src/trace_context.rsstashes the incomingtraceparentat the axum boundary keyed byX-Request-Id(injected when absent); the bridge pops it viaexternal_req_idlookup (tolerating vllm-server'scmpl-/chatcmpl-prefixes) and uses it as the parent of therequestroot span. Verified e2e on RTX 5070 Ti: single Tempo trace spans routerhttp_request→ routerhttp_client_request→ openinferrequest→queue/prefill/decode, for both/v1/completionsand/v1/chat/completions, with and without a client-supplied traceparent.The
X-Request-Idstash+correlation is a workaround and should not be permanent.Upstream fix
traceparent/tracestatefrom HTTP headers intoEngineCoreRequest.trace_headers(minimal pass-through; no gating, unlike the rejected #44567).Migration (once the upstream PR merges and we bump the vllm pin)
vllm-server/vllm-engine-core-clientpin to a rev containing the PR.bridge.rs: decode the parent fromEngineCoreRequest.trace_headers["traceparent"](SpanContext::decode_w3c_traceparent) instead ofTraceContextStashlookup. Therequest-span parent-resolution code stays; only the source changes.openinfer-vllm-frontend/src/trace_context.rsand its wiring inlib.rs(theexternal_req_idcorrelation and prefix-stripping go away entirely).Side observation (router upstream)
vllm-router's
http_client_requestspan occasionally shows a ~5s duration while its server span is ~300ms (observed on the non-streaming path); likely a span-lifetime bug in the router's instrumentation. Consider reporting to vllm-project/router separately.Ref: docs/subsystems/tracing/e2e-router-tracing.md