feat(httpx): Migrate to span first #6084
3 issues
Medium
Async span streaming path loses URL attributes if request fails - `sentry_sdk/integrations/httpx.py:208-213`
The async send function's span streaming path does not wrap await real_send() in a try/finally block, unlike the sync version (lines 98-104). If the HTTP request raises an exception (connection error, timeout, etc.), the attributes dict containing url.full, url.query, and url.fragment will never be set on the span via set_attributes(). This causes behavioral inconsistency between sync and async httpx clients and loses valuable debugging information in failure scenarios.
CODE_NAMESPACE attribute not set for StreamedSpan while other code attributes are - `sentry_sdk/tracing_utils.py:286-287`
On line 286, CODE_NAMESPACE is only set for LegacySpan (if namespace is not None and isinstance(span, LegacySpan)), but other code source attributes like code.line.number (line 280), code.file.path (line 302), and code.function.name (line 313) are set for both span types. This inconsistency means StreamedSpan will be missing the namespace attribute in telemetry data, which could affect debugging and observability of HTTP request sources.
Missing try/finally in async httpx span streaming path causes attributes to be lost on exceptions - `sentry_sdk/integrations/httpx.py:208-213`
In the async httpx client's span streaming path (lines 208-213), if await real_send() raises an exception, the attributes dictionary containing URL information (url.full, url.query, url.fragment) will never be set on the span. The sync client implementation correctly uses a try/finally block (lines 98-109 in the full file) to ensure set_attributes() is called even when exceptions occur. This inconsistency causes incomplete span data when async HTTP requests fail.
4 skills analyzed
| Skill | Findings | Duration | Cost |
|---|---|---|---|
| code-review | 2 | 7m 5s | $2.58 |
| find-bugs | 1 | 4m 30s | $6.51 |
| skill-scanner | 0 | 3m 25s | $1.23 |
| security-review | 0 | 5m 17s | $1.28 |
Duration: 20m 17s · Tokens: 6.1M in / 59.3k out · Cost: $11.64 (+merge: $0.00, +fix_gate: $0.01, +dedup: $0.03, +extraction: $0.01)