feat(redis): Support streaming spans #6083
3 issues
code-review: Found 3 issues (1 high, 2 medium)
High
NameError: Span is only imported under TYPE_CHECKING but used at runtime - `sentry_sdk/integrations/redis/utils.py:115`
The Span class is imported only under TYPE_CHECKING (line 17), which means it's not available at runtime. However, isinstance(span, Span) is called at line 115, which will raise NameError: name 'Span' is not defined whenever _set_pipeline_data is called with any span type.
Medium
Span resources leak when Redis command execution raises an exception - `sentry_sdk/integrations/redis/_async_common.py:145-156`
The _sentry_execute_command function manually calls __enter__() and __exit__() on spans (lines 126, 145, 152, 156) without try/finally protection. If await old_execute_command() on line 150 raises an exception, neither db_span.__exit__() nor cache_span.__exit__() will be called. This causes spans to never be finished/ended, leading to resource leaks and orphaned spans in the tracing system. Additionally, the span status won't be set to ERROR since __exit__ is called with (None, None, None) even in successful cases.
Unbound variable 'value' used in finally block when exception occurs - `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), which will raise a NameError. While capture_internal_exceptions() will catch this error silently, it prevents proper cache span data from being set and masks the actual exception behavior. The variable should be initialized to None before the try block.
Duration: 1m 34s · Tokens: 1.0M in / 13.3k out · Cost: $1.85 (+extraction: $0.01, +merge: $0.00, +fix_gate: $0.00)
Annotations
Check failure on line 115 in sentry_sdk/integrations/redis/utils.py
sentry-warden / warden: code-review
NameError: Span is only imported under TYPE_CHECKING but used at runtime
The `Span` class is imported only under `TYPE_CHECKING` (line 17), which means it's not available at runtime. However, `isinstance(span, Span)` is called at line 115, which will raise `NameError: name 'Span' is not defined` whenever `_set_pipeline_data` is called with any span type.
Check warning on line 156 in sentry_sdk/integrations/redis/_async_common.py
sentry-warden / warden: code-review
Span resources leak when Redis command execution raises an exception
The `_sentry_execute_command` function manually calls `__enter__()` and `__exit__()` on spans (lines 126, 145, 152, 156) without try/finally protection. If `await old_execute_command()` on line 150 raises an exception, neither `db_span.__exit__()` nor `cache_span.__exit__()` will be called. This causes spans to never be finished/ended, leading to resource leaks and orphaned spans in the tracing system. Additionally, the span status won't be set to ERROR since `__exit__` is called with `(None, None, None)` even in successful cases.
Check warning on line 158 in sentry_sdk/integrations/redis/_sync_common.py
sentry-warden / warden: code-review
Unbound variable 'value' used in finally block when exception occurs
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)`, which will raise a `NameError`. While `capture_internal_exceptions()` will catch this error silently, it prevents proper cache span data from being set and masks the actual exception behavior. The variable should be initialized to `None` before the try block.