feat(sqlalchemy): Support span streaming #6132
3 issues
find-bugs: Found 3 issues (1 high, 1 medium, 1 low)
High
Test uses StreamedSpan private attributes on NoOpSpan, causing AttributeError - `tests/integrations/sqlalchemy/test_sqlalchemy.py:1067-1068`
In streaming mode, record_sql_queries calls sentry_sdk.start_span() which delegates to Scope.start_span(). When streaming is enabled, Scope.start_span() returns NoOpSpan() (scope.py:1214). The test then tries to set _start_timestamp and _timestamp (with underscore prefix) on this NoOpSpan, but NoOpSpan inherits from Span which only has start_timestamp and timestamp (without underscore) in __slots__. This causes an AttributeError because NoOpSpan doesn't allow arbitrary attribute assignment.
Also found at:
tests/integrations/sqlalchemy/test_sqlalchemy.py:1212-1213tests/integrations/sqlalchemy/test_sqlalchemy.py:293
Medium
StreamedSpan handling code is unreachable - spans are never StreamedSpan instances - `sentry_sdk/integrations/sqlalchemy.py:101-104`
The isinstance(span, StreamedSpan) check on line 101 will never be true. The span comes from record_sql_queries() which internally calls sentry_sdk.start_span(). When span streaming is enabled, sentry_sdk.start_span() returns NoOpSpan (not StreamedSpan). When streaming is disabled, it returns Span. Neither is a StreamedSpan, making this error handling code unreachable.
Also found at:
sentry_sdk/integrations/sqlalchemy.py:142-177
Low
Dead code: span_streaming conditional inside else branch will never execute True path - `tests/integrations/sqlalchemy/test_sqlalchemy.py:989-994`
In test_no_query_source_if_duration_too_short, inside the else: branch (line 962), the fake_record_sql_queries class contains an if span_streaming: check (lines 989-994). Since this code is inside the else: # span_streaming is False branch, the if span_streaming: block (lines 989-991) is unreachable dead code. While the test still works correctly because the else: path is taken, this appears to be an artifact of copy-paste during refactoring that should be cleaned up.
Duration: 11m 50s · Tokens: 6.8M in / 54.3k out · Cost: $8.18 (+extraction: $0.01, +merge: $0.00, +fix_gate: $0.01)
Annotations
Check failure on line 1068 in tests/integrations/sqlalchemy/test_sqlalchemy.py
sentry-warden / warden: find-bugs
Test uses StreamedSpan private attributes on NoOpSpan, causing AttributeError
In streaming mode, `record_sql_queries` calls `sentry_sdk.start_span()` which delegates to `Scope.start_span()`. When streaming is enabled, `Scope.start_span()` returns `NoOpSpan()` (scope.py:1214). The test then tries to set `_start_timestamp` and `_timestamp` (with underscore prefix) on this `NoOpSpan`, but `NoOpSpan` inherits from `Span` which only has `start_timestamp` and `timestamp` (without underscore) in `__slots__`. This causes an `AttributeError` because `NoOpSpan` doesn't allow arbitrary attribute assignment.
Check failure on line 1213 in tests/integrations/sqlalchemy/test_sqlalchemy.py
sentry-warden / warden: find-bugs
[M6Z-WXV] Test uses StreamedSpan private attributes on NoOpSpan, causing AttributeError (additional location)
In streaming mode, `record_sql_queries` calls `sentry_sdk.start_span()` which delegates to `Scope.start_span()`. When streaming is enabled, `Scope.start_span()` returns `NoOpSpan()` (scope.py:1214). The test then tries to set `_start_timestamp` and `_timestamp` (with underscore prefix) on this `NoOpSpan`, but `NoOpSpan` inherits from `Span` which only has `start_timestamp` and `timestamp` (without underscore) in `__slots__`. This causes an `AttributeError` because `NoOpSpan` doesn't allow arbitrary attribute assignment.
Check failure on line 293 in tests/integrations/sqlalchemy/test_sqlalchemy.py
sentry-warden / warden: find-bugs
[M6Z-WXV] Test uses StreamedSpan private attributes on NoOpSpan, causing AttributeError (additional location)
In streaming mode, `record_sql_queries` calls `sentry_sdk.start_span()` which delegates to `Scope.start_span()`. When streaming is enabled, `Scope.start_span()` returns `NoOpSpan()` (scope.py:1214). The test then tries to set `_start_timestamp` and `_timestamp` (with underscore prefix) on this `NoOpSpan`, but `NoOpSpan` inherits from `Span` which only has `start_timestamp` and `timestamp` (without underscore) in `__slots__`. This causes an `AttributeError` because `NoOpSpan` doesn't allow arbitrary attribute assignment.
Check warning on line 104 in sentry_sdk/integrations/sqlalchemy.py
sentry-warden / warden: find-bugs
StreamedSpan handling code is unreachable - spans are never StreamedSpan instances
The `isinstance(span, StreamedSpan)` check on line 101 will never be true. The span comes from `record_sql_queries()` which internally calls `sentry_sdk.start_span()`. When span streaming is enabled, `sentry_sdk.start_span()` returns `NoOpSpan` (not `StreamedSpan`). When streaming is disabled, it returns `Span`. Neither is a `StreamedSpan`, making this error handling code unreachable.
Check warning on line 177 in sentry_sdk/integrations/sqlalchemy.py
sentry-warden / warden: find-bugs
[FY5-ZHS] StreamedSpan handling code is unreachable - spans are never StreamedSpan instances (additional location)
The `isinstance(span, StreamedSpan)` check on line 101 will never be true. The span comes from `record_sql_queries()` which internally calls `sentry_sdk.start_span()`. When span streaming is enabled, `sentry_sdk.start_span()` returns `NoOpSpan` (not `StreamedSpan`). When streaming is disabled, it returns `Span`. Neither is a `StreamedSpan`, making this error handling code unreachable.