Skip to content

.

4b2147d
Select commit
Loading
Failed to load commit list.
Draft

[do not merge] feat: Span streaming & new span API #5551

.
4b2147d
Select commit
Loading
Failed to load commit list.
@sentry/warden / warden: code-review completed Mar 16, 2026 in 23m 41s

5 issues

code-review: Found 5 issues (2 high, 3 medium)

High

Swapped method assignments cause AttributeError at runtime - `sentry_sdk/integrations/openai_agents/utils.py:55-58`

The code assigns span.set_attribute for Span instances and span.set_data for StreamedSpan instances, but these methods don't exist on those respective classes. Span (from tracing.py) has set_data() but not set_attribute(), while StreamedSpan (from traces.py) has set_attribute() but not set_data(). This will cause an AttributeError at runtime when _record_exception_on_span is called.

Also found at:

  • sentry_sdk/integrations/sqlalchemy.py:102
UnboundLocalError when Redis command raises exception - `sentry_sdk/integrations/redis/_sync_common.py:158`

In sentry_patched_execute_command, the value variable is assigned inside the try block (line 152), but it's accessed in the finally block (line 158). If old_execute_command raises an exception, value is never assigned, causing an UnboundLocalError when _set_cache_data(cache_span, self, cache_properties, value) is called. This will mask the original Redis exception with an internal error.

Medium

Span streaming creates spans for HTTP methods that should be ignored - `sentry_sdk/integrations/asgi.py:238-241`

In the span streaming branch (lines 218-241), when ty is 'http' but the method is NOT in http_methods_to_capture, the code still creates a span via sentry_sdk.traces.start_span() (line 238). In the legacy branch, transaction would remain None and nullcontext() would be used instead. This behavioral difference causes spans to be created and sent for HTTP methods that users have explicitly configured to ignore, potentially leading to excessive span volume and unexpected costs.

HTTP status code attribute missing in StreamedSpan path - `sentry_sdk/integrations/httpx.py:116-118`

In the synchronous send() function, when span_streaming is enabled, the HTTP response status code is not being set as an attribute on the span. The legacy Span.set_http_status() method sets SPANDATA.HTTP_STATUS_CODE (i.e., http.response.status_code), but the StreamedSpan path only sets the status string ("ok"/"error") and the "reason" attribute. This causes a data inconsistency where spans sent in streaming mode will be missing the HTTP status code, which is important telemetry data for HTTP client spans.

Also found at:

  • sentry_sdk/integrations/httpx.py:199-201
Missing exception handling causes span resource leaks in async Redis client - `sentry_sdk/integrations/redis/_async_common.py:145-147`

The async _sentry_execute_command function manually enters db_span and cache_span using __enter__() but lacks a try...finally block to ensure __exit__() is called when old_execute_command raises an exception. In contrast, the sync version in _sync_common.py wraps the call in try...finally. If the Redis command throws, spans won't be closed, the scope's active span won't be restored, and the error status won't be set on the spans.


Duration: 23m 32s · Tokens: 9.3M in / 109.1k out · Cost: $13.04 (+extraction: $0.01, +merge: $0.00, +fix_gate: $0.01)

Annotations

Check failure on line 58 in sentry_sdk/integrations/openai_agents/utils.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: code-review

Swapped method assignments cause AttributeError at runtime

The code assigns `span.set_attribute` for `Span` instances and `span.set_data` for `StreamedSpan` instances, but these methods don't exist on those respective classes. `Span` (from `tracing.py`) has `set_data()` but not `set_attribute()`, while `StreamedSpan` (from `traces.py`) has `set_attribute()` but not `set_data()`. This will cause an `AttributeError` at runtime when `_record_exception_on_span` is called.

Check failure on line 102 in sentry_sdk/integrations/sqlalchemy.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: code-review

[TDX-ZPZ] Swapped method assignments cause AttributeError at runtime (additional location)

The code assigns `span.set_attribute` for `Span` instances and `span.set_data` for `StreamedSpan` instances, but these methods don't exist on those respective classes. `Span` (from `tracing.py`) has `set_data()` but not `set_attribute()`, while `StreamedSpan` (from `traces.py`) has `set_attribute()` but not `set_data()`. This will cause an `AttributeError` at runtime when `_record_exception_on_span` is called.

Check failure on line 158 in sentry_sdk/integrations/redis/_sync_common.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: code-review

UnboundLocalError when Redis command raises exception

In `sentry_patched_execute_command`, the `value` variable is assigned inside the `try` block (line 152), but it's accessed in the `finally` block (line 158). If `old_execute_command` raises an exception, `value` is never assigned, causing an `UnboundLocalError` when `_set_cache_data(cache_span, self, cache_properties, value)` is called. This will mask the original Redis exception with an internal error.

Check warning on line 241 in sentry_sdk/integrations/asgi.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: code-review

Span streaming creates spans for HTTP methods that should be ignored

In the span streaming branch (lines 218-241), when `ty` is 'http' but the method is NOT in `http_methods_to_capture`, the code still creates a span via `sentry_sdk.traces.start_span()` (line 238). In the legacy branch, `transaction` would remain `None` and `nullcontext()` would be used instead. This behavioral difference causes spans to be created and sent for HTTP methods that users have explicitly configured to ignore, potentially leading to excessive span volume and unexpected costs.

Check warning on line 118 in sentry_sdk/integrations/httpx.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: code-review

HTTP status code attribute missing in StreamedSpan path

In the synchronous `send()` function, when `span_streaming` is enabled, the HTTP response status code is not being set as an attribute on the span. The legacy `Span.set_http_status()` method sets `SPANDATA.HTTP_STATUS_CODE` (i.e., `http.response.status_code`), but the `StreamedSpan` path only sets the status string ("ok"/"error") and the "reason" attribute. This causes a data inconsistency where spans sent in streaming mode will be missing the HTTP status code, which is important telemetry data for HTTP client spans.

Check warning on line 201 in sentry_sdk/integrations/httpx.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: code-review

[8GQ-3RQ] HTTP status code attribute missing in StreamedSpan path (additional location)

In the synchronous `send()` function, when `span_streaming` is enabled, the HTTP response status code is not being set as an attribute on the span. The legacy `Span.set_http_status()` method sets `SPANDATA.HTTP_STATUS_CODE` (i.e., `http.response.status_code`), but the `StreamedSpan` path only sets the status string ("ok"/"error") and the "reason" attribute. This causes a data inconsistency where spans sent in streaming mode will be missing the HTTP status code, which is important telemetry data for HTTP client spans.

Check warning on line 147 in sentry_sdk/integrations/redis/_async_common.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: code-review

Missing exception handling causes span resource leaks in async Redis client

The async `_sentry_execute_command` function manually enters `db_span` and `cache_span` using `__enter__()` but lacks a `try...finally` block to ensure `__exit__()` is called when `old_execute_command` raises an exception. In contrast, the sync version in `_sync_common.py` wraps the call in `try...finally`. If the Redis command throws, spans won't be closed, the scope's active span won't be restored, and the error status won't be set on the spans.