Skip to content

fix(otel): fix concurrency bug in TracingHook span tracking#492

Draft
simonvdk-mistral wants to merge 2 commits intomainfrom
svdk/fix/otel_tracing_concurrency_bug
Draft

fix(otel): fix concurrency bug in TracingHook span tracking#492
simonvdk-mistral wants to merge 2 commits intomainfrom
svdk/fix/otel_tracing_concurrency_bug

Conversation

@simonvdk-mistral
Copy link
Copy Markdown
Contributor

@simonvdk-mistral simonvdk-mistral commented Apr 17, 2026

Bug

TracingHook stored the active span as self.request_span — a single instance attribute shared across all concurrent requests. When two requests were in-flight simultaneously, they clobbered each other's span:

Request A                          Request B
─────────                          ─────────
1. before_request()
   self.request_span = span_A
                                   2. before_request()
                                      self.request_span = span_B  ← overwrites span_A
3. after_success()
   uses span_B instead of span_A  ← wrong span
   self.request_span = None
                                   4. after_success()
                                      self.request_span is None   ← span lost

Impact: spans attributed to wrong requests, spans never closed (leaked), response attributes applied to wrong traces.

Reproducing

The test test_concurrent_async_requests_get_correct_spans reproduces this using a real Mistral client with asyncio.gather and a mock transport. An asyncio.Event gate ensures both before_request hooks fire before either response returns, guaranteeing the interleaving.

Fix

Store the span on request.extensions["_tracing_span"] instead of self.request_span. Retrieve it in after_success/after_error via response.request.extensions. This is the same extensions dict that httpx uses internally (e.g. for timeouts) — it is purely in-memory metadata, never serialized or sent over the wire.

Note: no other hook had this bug — TracingHook was the only one storing per-request state on self.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant