[do not merge] feat: Span streaming & new span API #5551
8 issues
High
UnboundLocalError when Redis command raises exception - `sentry_sdk/integrations/redis/_sync_common.py:158`
In sentry_patched_execute_command, if old_execute_command raises an exception, the finally block will attempt to access value in the call to _set_cache_data(cache_span, self, cache_properties, value), but value was never assigned. This causes an UnboundLocalError: local variable 'value' referenced before assignment, which will crash the application instead of propagating the original Redis exception.
Also found at:
sentry_sdk/integrations/redis/_async_common.py:145-147
StreamedSpan.set_status() method does not exist, causing AttributeError at runtime - `sentry_sdk/integrations/sqlalchemy.py:102`
The code calls span.set_status(SpanStatus.ERROR) on line 102 when the span is a StreamedSpan. However, StreamedSpan class (defined in sentry_sdk/traces.py) does not have a set_status() method - it only has a status property setter. This will raise an AttributeError at runtime when a SQL error occurs in streaming mode. The fix should use property assignment: span.status = SpanStatus.ERROR.
Also found at:
sentry_sdk/integrations/graphene.py:174-175
StreamedSpan has no set_status method - will raise AttributeError at runtime - `sentry_sdk/integrations/sqlalchemy.py:102`
The code calls span.set_status(SpanStatus.ERROR) when span is a StreamedSpan, but StreamedSpan class does not have a set_status method. It only has a status property setter. When a SQL error occurs in streaming mode, this will raise an AttributeError: 'StreamedSpan' object has no attribute 'set_status', preventing proper error handling and potentially breaking the application.
Medium
HTTP status code not recorded for StreamedSpan in stdlib httplib integration - `sentry_sdk/integrations/stdlib.py:175-177`
When using span streaming mode, the HTTP status code (e.g., 200, 404, 500) is not recorded as an attribute on the span. Only the status ('ok'/'error') and 'reason' are set. Compare with wsgi.py line 235 which correctly calls span.set_attribute("http.response.status_code", status_int) for StreamedSpan. This results in data loss - users won't see the actual HTTP status code in their traces when using span streaming mode.
Missing HTTP status code attribute for StreamedSpan in sync client - `sentry_sdk/integrations/httpx.py:117-119`
When span streaming is enabled, the StreamedSpan sets span.status and reason attribute but does NOT set the HTTP status code attribute (SPANDATA.HTTP_STATUS_CODE / http.response.status_code). The legacy Span.set_http_status() method sets this attribute at line 635 of sentry_sdk/tracing.py. This results in incomplete span telemetry data - users won't see the actual HTTP status code in their traces when using span streaming mode.
Also found at:
sentry_sdk/integrations/httpx.py:200-202sentry_sdk/integrations/stdlib.py:175-177
NameError when Redis command raises exception - `sentry_sdk/integrations/redis/_sync_common.py:158`
When old_execute_command raises an exception, the value variable is never assigned. The finally block then attempts to use value in _set_cache_data(cache_span, self, cache_properties, value), causing a NameError. While wrapped in capture_internal_exceptions(), this silently loses cache span metadata and may cause confusing internal error logs.
Also found at:
sentry_sdk/integrations/strawberry.py:226
Low
Span name 'subprocess popen' is incorrect for subprocess.wait operation - `sentry_sdk/integrations/stdlib.py:322`
The sentry_patched_popen_wait function incorrectly sets the span name to 'subprocess popen' when it should be 'subprocess wait' to match the OP.SUBPROCESS_WAIT operation and the method being wrapped. This inconsistency will make it harder to identify subprocess.wait spans in the Sentry UI, as the span name won't match the operation being performed.
Inconsistent span name 'subprocess popen' for SUBPROCESS_WAIT operation - `sentry_sdk/integrations/stdlib.py:322-323`
In sentry_patched_popen_wait, the span name is set to 'subprocess popen' (line 322) while the operation is OP.SUBPROCESS_WAIT (line 323). This appears to be a copy-paste error. The other subprocess functions use consistent naming: 'subprocess communicate' with SUBPROCESS_COMMUNICATE. This inconsistency will cause confusion when analyzing traces since the span name doesn't match the actual operation being performed.
4 skills analyzed
| Skill | Findings | Duration | Cost |
|---|---|---|---|
| code-review | 4 | 10m 43s | $12.06 |
| find-bugs | 4 | 20m 42s | $18.92 |
| skill-scanner | 0 | 23m 31s | $6.43 |
| security-review | 0 | 27m 55s | $7.86 |
Duration: 82m 51s · Tokens: 27.2M in / 302.4k out · Cost: $45.35 (+extraction: $0.04, +merge: $0.01, +fix_gate: $0.02, +dedup: $0.03)