You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
startInteractionSpan in packages/core/src/telemetry/session-tracing.ts:143 creates the qwen-code.interaction span without passing the session root context as parent, so the OTel SDK assigns it a fresh random trace id. The interaction span ends up in its own one-span trace, while its semantic children (llm_request, tool, tool.execution) — which DO inherit the session context — land in the sessionId-derived trace. The hierarchy breaks across two unrelated trace ids.
Repro (real production data)
Session 33878ff9-1467-43ef-a692-634a21bbb1bf (cn-beijing, 2026-05-25 09:53–09:56) produced two distinct trace ids for the same session:
the qwen-code.interaction span only (uses OTel-generated random trace id)
Both traces carry the same session.id tag, but they share no OTel trace context. Any trace viewer (ARMS / Jaeger / Zipkin) renders them as two disconnected items.
Root cause
session-tracing.ts has 4 startSpan call sites; only startInteractionSpan is missing the ctx parameter:
PR #4126 (feat(telemetry): unify span creation paths for hierarchical trace tree) did most of the heavy lifting — it wired llm_request / tool / tool.execution to inherit the parent interaction context. But it changed only the children's context propagation, not interaction itself. So we ended up with a half-fixed hierarchy: children correctly chain to the sessionId-derived trace id, parent doesn't.
Impact
Hierarchy is broken in any trace viewer. A user looking at trace 4acca441… sees llm_request, tool, api_response spans as orphaned siblings under the synthetic session root, with no wrapping interaction span to group them by user turn.
session.id → traceId derivation lookups silently miss data. Any tool that takes a sessionId and computes traceId = sha256(sessionId)[:32] then calls GetTrace will only fetch the log-bridge trace, completely missing every native interaction span (one per turn). This is the bug pattern the qwen-trace-query skill recently switched away from after hitting it in practice.
interaction.sequence counter becomes confusing. Each interaction span sits in its own trace, so the sequence numbers (1, 2, 3, …) appear across N unrelated traces rather than as ordered children of one session trace.
TL;DR
startInteractionSpaninpackages/core/src/telemetry/session-tracing.ts:143creates theqwen-code.interactionspan without passing the session root context as parent, so the OTel SDK assigns it a fresh random trace id. The interaction span ends up in its own one-span trace, while its semantic children (llm_request,tool,tool.execution) — which DO inherit the session context — land in the sessionId-derived trace. The hierarchy breaks across two unrelated trace ids.Repro (real production data)
Session
33878ff9-1467-43ef-a692-634a21bbb1bf(cn-beijing, 2026-05-25 09:53–09:56) produced two distinct trace ids for the same session:4acca441dba8071e51177f7c82fe0d07sha256(sessionId)[:32])54dbac5a0e1437165971820716388282qwen-code.interactionspan only (uses OTel-generated random trace id)Both traces carry the same
session.idtag, but they share no OTel trace context. Any trace viewer (ARMS / Jaeger / Zipkin) renders them as two disconnected items.Root cause
session-tracing.tshas 4startSpancall sites; onlystartInteractionSpanis missing thectxparameter:The intent that all session spans share one trace id is documented in
tracer.ts:252-254:Why #4126 didn't catch this
PR #4126 (
feat(telemetry): unify span creation paths for hierarchical trace tree) did most of the heavy lifting — it wiredllm_request/tool/tool.executionto inherit the parent interaction context. But it changed only the children's context propagation, not interaction itself. So we ended up with a half-fixed hierarchy: children correctly chain to the sessionId-derived trace id, parent doesn't.Impact
4acca441…seesllm_request,tool,api_responsespans as orphaned siblings under the synthetic session root, with no wrappinginteractionspan to group them by user turn.session.id → traceIdderivation lookups silently miss data. Any tool that takes asessionIdand computestraceId = sha256(sessionId)[:32]then callsGetTracewill only fetch the log-bridge trace, completely missing every nativeinteractionspan (one per turn). This is the bug pattern theqwen-trace-queryskill recently switched away from after hitting it in practice.interaction.sequencecounter becomes confusing. Each interaction span sits in its own trace, so the sequence numbers (1,2,3, …) appear across N unrelated traces rather than as ordered children of one session trace.Suggested fix
3 lines in
session-tracing.ts:143:Or equivalently call the existing
startSpanWithContexthelper intracer.ts:198, which already wraps this pattern.A regression test would assert that
interaction.spanContext().traceId === deriveTraceId(sessionId), matching the other three span types.Affected version
Reproduced on
origin/main @ 84f408017(latest as of this writing).Related
feat(telemetry): unify span creation paths for hierarchical trace tree(the work that addressed the children but missed the parent)packages/core/src/telemetry/session-tracing.ts:143— bug locationpackages/core/src/telemetry/tracer.ts:252-266—createSessionRootContext(the context that should be the interaction's parent)