Skip to content

sync common

08e896a
Select commit
Loading
Failed to load commit list.
Merged

feat(redis): Support streaming spans #6083

sync common
08e896a
Select commit
Loading
Failed to load commit list.
@sentry/warden / warden completed Apr 16, 2026 in 4m 4s

5 issues

High

Span leaks when Redis command throws exception - `sentry_sdk/integrations/redis/_async_common.py:145-147`

The _sentry_execute_command function manually enters db_span and cache_span contexts (lines 126 and 145) but doesn't use try/finally to ensure __exit__ is called on exceptions. If await old_execute_command() raises an exception, the spans' __exit__ methods are never called, causing span leaks and potentially corrupting scope state. The synchronous version in _sync_common.py correctly uses try/finally for this pattern.

Medium

NameError raised when Redis command fails with exception - `sentry_sdk/integrations/redis/_sync_common.py:158`

In sentry_patched_execute_command, 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 capture_internal_exceptions() catches this, it results in unnecessary internal exception noise and obscures the real error from monitoring.

Missing exception handling in async _sentry_execute_command causes span leak on Redis errors - `sentry_sdk/integrations/redis/_async_common.py:145-147`

The async _sentry_execute_command function does not wrap the Redis command execution in a try/finally block. When old_execute_command raises an exception, db_span.__exit__() and cache_span.__exit__() are never called, leaving spans unclosed. The sync version in _sync_common.py correctly uses try/finally (lines 151-160).

Also found at:

  • sentry_sdk/integrations/redis/_async_common.py:147-148
UnboundLocalError when Redis command raises exception - `sentry_sdk/integrations/redis/_sync_common.py:158`

In sentry_patched_execute_command, the finally block calls _set_cache_data(cache_span, self, cache_properties, value) which references value. However, value is only assigned if old_execute_command succeeds. If old_execute_command raises an exception, value is undefined, causing an UnboundLocalError in the finally block. While capture_internal_exceptions() wraps this call and will suppress the error, this still creates an unnecessary exception that gets silently caught, and the span cleanup logic after it (cache_span.__exit__) will still execute successfully.

Low

Missing test coverage for StreamedSpan code path in Redis cache module - `sentry_sdk/integrations/redis/modules/caches.py:89-92`

The new StreamedSpan code path in _set_cache_data lacks dedicated test coverage. Existing Redis tests do not include tests with _experiments={"trace_lifecycle": "stream"} enabled. While the implementation correctly uses isinstance checks to differentiate span types and both set_attribute and set_data have compatible signatures, the new streaming path is untested.

4 skills analyzed
Skill Findings Duration Cost
code-review 3 3m 54s $1.84
find-bugs 2 2m 30s $2.19
skill-scanner 0 40.1s $0.73
security-review 0 1m 8s $0.81

Duration: 8m 12s · Tokens: 3.2M in / 37.1k out · Cost: $5.60 (+extraction: $0.01, +merge: $0.00, +fix_gate: $0.01, +dedup: $0.00)