Skip to content

.

38b5933
Select commit
Loading
Failed to load commit list.
Merged

feat(sqlalchemy): Support span streaming #6132

.
38b5933
Select commit
Loading
Failed to load commit list.
@sentry/warden / warden completed Apr 24, 2026 in 12m 7s

6 issues

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-1213
  • tests/integrations/sqlalchemy/test_sqlalchemy.py:293

Medium

Potential runtime error if no root span found in streamed spans - `tests/conftest.py:488-490`

When root_span=None (streaming mode), the code attempts to find a root span by looking for a span without parent_span_id. If no such span exists in the list, root_span remains None, and line 509 will raise a runtime error when calling render_span(root_span). This could cause cryptic test failures.

Also found at:

  • tests/conftest.py:485-487
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

Missing SERVER_ADDRESS assertion in span_streaming path of test_transactions - `tests/integrations/sqlalchemy/test_sqlalchemy.py:162`

The span streaming branch of test_transactions only asserts SPANDATA.SERVER_PORT not in span["attributes"], while the non-streaming branch checks both SPANDATA.SERVER_ADDRESS not in span["data"] and SPANDATA.SERVER_PORT not in span["data"]. This asymmetry means the streaming path does not verify SERVER_ADDRESS is absent, reducing test coverage for the span streaming feature.

Also found at:

  • tests/integrations/sqlalchemy/test_sqlalchemy.py:293
Span streaming test path missing CODE_NAMESPACE assertion - `tests/integrations/sqlalchemy/test_sqlalchemy.py:811-813`

The span streaming branch (lines 811-813) only checks for CODE_LINE_NUMBER, CODE_FILE_PATH, and CODE_FUNCTION_NAME attributes, but omits the CODE_NAMESPACE check that exists in the non-streaming branch (lines 864-867, 871). This asymmetry in test coverage could allow a regression where span streaming mode fails to include namespace information.

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.

4 skills analyzed
Skill Findings Duration Cost
code-review 3 8m 56s $2.98
find-bugs 3 11m 50s $8.17
skill-scanner 0 6m 21s $0.89
security-review 0 4m 39s $0.74

Duration: 31m 47s · Tokens: 9.7M in / 92.1k out · Cost: $12.80 (+extraction: $0.01, +merge: $0.01, +fix_gate: $0.01, +dedup: $0.00)