feat(sqlalchemy): Support span streaming #6132
4 issues
Medium
Inconsistent handling of None query between streaming and non-streaming paths - `sentry_sdk/tracing_utils.py:224`
The streaming path (line 212) handles None query with a fallback to <unknown SQL query>, but the non-streaming path (line 224) passes query directly without the same check. This inconsistency means that if query is None, the streaming path will create a span named <unknown SQL query> while the non-streaming path will create a span with None as the name, leading to different behavior depending on the configuration.
Also found at:
tests/integrations/sqlalchemy/test_sqlalchemy.py:162tests/integrations/sqlalchemy/test_sqlalchemy.py:293
Low
Type annotation mismatch in _handle_error: declared as Optional[Span] but handles StreamedSpan - `sentry_sdk/integrations/sqlalchemy.py:107-113`
The type annotation on line 107 declares span as Optional[Span], but lines 110-111 use isinstance(span, StreamedSpan) to handle StreamedSpan objects. This inconsistency could confuse static analysis tools and developers maintaining the code. The annotation should be Optional[Union[Span, StreamedSpan]] to match the actual runtime behavior.
Also found at:
tests/conftest.py:479-507
Type annotation in _handle_error does not match actual span type - `sentry_sdk/integrations/sqlalchemy.py:107-113`
The type annotation span: "Optional[Span]" on line 107 declares the span as the legacy Span type only, but the code immediately checks isinstance(span, StreamedSpan) on line 110, indicating the span can also be a StreamedSpan. This inconsistency could mislead type checkers and developers about the actual types flowing through this function. While not a runtime bug (Python doesn't enforce type annotations), it could cause static analysis tools to report false negatives or positives.
Inconsistent handling of None query in streaming vs non-streaming paths - `sentry_sdk/tracing_utils.py:212-224`
In record_sql_queries_supporting_streaming, when span streaming is enabled (line 212), a None query is replaced with "<unknown SQL query>" for the span name. However, in the non-streaming path (line 224), query is passed directly to sentry_sdk.start_span without this fallback, maintaining the same behavior as the original record_sql_queries. Additionally, the breadcrumb on line 208 uses query directly as the message without the fallback, creating an inconsistency where the streaming span name would differ from the breadcrumb message when query is None.
4 skills analyzed
| Skill | Findings | Duration | Cost |
|---|---|---|---|
| code-review | 2 | 12m 32s | $4.44 |
| find-bugs | 2 | 7m 35s | $8.13 |
| skill-scanner | 0 | 5m 52s | $1.41 |
| security-review | 0 | 4m | $1.70 |
Duration: 29m 59s · Tokens: 9.9M in / 108.8k out · Cost: $15.71 (+extraction: $0.02, +merge: $0.00, +fix_gate: $0.01, +dedup: $0.01)