Skip to content

cleanup

cc51564
Select commit
Loading
Failed to load commit list.
Sign in for the full log view
Draft

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

cleanup
cc51564
Select commit
Loading
Failed to load commit list.
GitHub Actions / warden: code-review completed Mar 11, 2026 in 20m 22s

6 issues

code-review: Found 6 issues (3 high, 2 medium, 1 low)

High

Spans leak when Redis command throws exception - `sentry_sdk/integrations/redis/_async_common.py:145`

When old_execute_command raises an exception, db_span.__exit__() and cache_span.__exit__() are never called because there's no try/finally block wrapping the await call. This differs from the sync version in _sync_common.py which correctly uses try/finally at lines 151-160. Leaking spans will cause incorrect timing data and potential memory/scope issues.

Also found at:

  • sentry_sdk/integrations/redis/_sync_common.py:158
AttributeError when using legacy Span class - missing _to_traceparent, _to_baggage, _get_trace_context methods - `sentry_sdk/scope.py:587-611`

The code calls self.span._to_traceparent(), self.span._to_baggage(), and self._span._get_trace_context() on the span object. However, the Span type from tracing.py (used in legacy non-streaming mode) only defines the non-underscore versions: to_traceparent(), to_baggage(), and get_trace_context(). This will cause AttributeError at runtime when using the SDK in non-streaming mode.

NoOpStreamedSpan._get_trace_context() and _dynamic_sampling_context() will raise AttributeError - `sentry_sdk/traces.py:586`

Setting self._segment = None on line 586 without overriding _dynamic_sampling_context() and _get_trace_context() in NoOpStreamedSpan causes a runtime error. When scope.get_trace_context() is called with an active NoOpStreamedSpan, it invokes the inherited _get_trace_context() which calls _dynamic_sampling_context(), which accesses self._segment._get_baggage() - resulting in AttributeError: 'NoneType' object has no attribute '_get_baggage'.

Medium

Span streaming mode ignores http_methods_to_capture filter for HTTP requests - `sentry_sdk/integrations/asgi.py:238-241`

In the span streaming branch (lines 218-241), a span is always created via start_span() at line 238, regardless of whether the HTTP method is in http_methods_to_capture. In contrast, the legacy branch (lines 243-275) only creates a transaction when method in self.http_methods_to_capture. This causes HTTP requests with methods like OPTIONS, HEAD, etc. (if not in the filter) to create unnecessary spans in streaming mode, potentially impacting performance and creating unwanted telemetry data.

HTTP status code attribute missing for StreamedSpan in sync client - `sentry_sdk/integrations/httpx.py:117-118`

When using span streaming mode, the HTTP response status code is not recorded as an attribute via SPANDATA.HTTP_STATUS_CODE. Only span.status is set to "ok" or "error". This breaks consistency with the legacy API where set_http_status() sets both the status and the numeric status code. Features that depend on the status code attribute (like trace_ignore_status_codes filtering or breadcrumb creation) will not work correctly for streamed spans.

Also found at:

  • sentry_sdk/integrations/httpx.py:200-201

Low

isinstance check does not distinguish StreamedSpan from NoOpStreamedSpan - `tests/tracing/test_span_streaming.py:1008`

The isinstance(span, StreamedSpan) assertion on line 1008 will always pass even when span is a NoOpStreamedSpan, because NoOpStreamedSpan inherits from StreamedSpan. This test is meant to verify that non-ignored spans are real StreamedSpan instances (not NoOp), but the current check provides a false sense of security since it cannot distinguish between the two types. The test relies solely on the span.sampled is True check which precedes it, making the isinstance assertion redundant and misleading.


Duration: 20m 12s · Tokens: 15.0M in / 172.9k out · Cost: $20.23 (+extraction: $0.01, +merge: $0.00, +fix_gate: $0.01)

Annotations

Check failure on line 145 in sentry_sdk/integrations/redis/_async_common.py

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

Spans leak when Redis command throws exception

When `old_execute_command` raises an exception, `db_span.__exit__()` and `cache_span.__exit__()` are never called because there's no `try/finally` block wrapping the await call. This differs from the sync version in `_sync_common.py` which correctly uses `try/finally` at lines 151-160. Leaking spans will cause incorrect timing data and potential memory/scope issues.

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

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

[8YY-F82] Spans leak when Redis command throws exception (additional location)

When `old_execute_command` raises an exception, `db_span.__exit__()` and `cache_span.__exit__()` are never called because there's no `try/finally` block wrapping the await call. This differs from the sync version in `_sync_common.py` which correctly uses `try/finally` at lines 151-160. Leaking spans will cause incorrect timing data and potential memory/scope issues.

Check failure on line 611 in sentry_sdk/scope.py

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

AttributeError when using legacy Span class - missing _to_traceparent, _to_baggage, _get_trace_context methods

The code calls `self.span._to_traceparent()`, `self.span._to_baggage()`, and `self._span._get_trace_context()` on the span object. However, the `Span` type from `tracing.py` (used in legacy non-streaming mode) only defines the non-underscore versions: `to_traceparent()`, `to_baggage()`, and `get_trace_context()`. This will cause `AttributeError` at runtime when using the SDK in non-streaming mode.

Check failure on line 586 in sentry_sdk/traces.py

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

NoOpStreamedSpan._get_trace_context() and _dynamic_sampling_context() will raise AttributeError

Setting `self._segment = None` on line 586 without overriding `_dynamic_sampling_context()` and `_get_trace_context()` in `NoOpStreamedSpan` causes a runtime error. When `scope.get_trace_context()` is called with an active `NoOpStreamedSpan`, it invokes the inherited `_get_trace_context()` which calls `_dynamic_sampling_context()`, which accesses `self._segment._get_baggage()` - resulting in `AttributeError: 'NoneType' object has no attribute '_get_baggage'`.

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

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

Span streaming mode ignores http_methods_to_capture filter for HTTP requests

In the span streaming branch (lines 218-241), a span is always created via `start_span()` at line 238, regardless of whether the HTTP method is in `http_methods_to_capture`. In contrast, the legacy branch (lines 243-275) only creates a transaction when `method in self.http_methods_to_capture`. This causes HTTP requests with methods like OPTIONS, HEAD, etc. (if not in the filter) to create unnecessary spans in streaming mode, potentially impacting performance and creating unwanted telemetry data.

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

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

HTTP status code attribute missing for StreamedSpan in sync client

When using span streaming mode, the HTTP response status code is not recorded as an attribute via `SPANDATA.HTTP_STATUS_CODE`. Only `span.status` is set to "ok" or "error". This breaks consistency with the legacy API where `set_http_status()` sets both the status and the numeric status code. Features that depend on the status code attribute (like `trace_ignore_status_codes` filtering or breadcrumb creation) will not work correctly for streamed spans.

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

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

[HXN-2TP] HTTP status code attribute missing for StreamedSpan in sync client (additional location)

When using span streaming mode, the HTTP response status code is not recorded as an attribute via `SPANDATA.HTTP_STATUS_CODE`. Only `span.status` is set to "ok" or "error". This breaks consistency with the legacy API where `set_http_status()` sets both the status and the numeric status code. Features that depend on the status code attribute (like `trace_ignore_status_codes` filtering or breadcrumb creation) will not work correctly for streamed spans.