[do not merge] feat: Span streaming & new span API#5551
[do not merge] feat: Span streaming & new span API#5551sentrivana wants to merge 149 commits intomasterfrom
Conversation
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog. This PR will not appear in the changelog. 🤖 This preview updates automatically when you update the PR. |
Codecov Results 📊✅ 13 passed | Total: 13 | Pass Rate: 100% | Execution Time: 4.65s All tests are passing successfully. ❌ Patch coverage is 22.65%. Project has 14385 uncovered lines. Files with missing lines (180)
Generated by Codecov Action |
There was a problem hiding this comment.
Race condition causes span loss when buffer is at flush threshold (sentry_sdk/_span_batcher.py:19)
When MAX_BEFORE_FLUSH (1000) equals MAX_BEFORE_DROP (1000), a race condition exists where spans are unnecessarily dropped. After the 1000th span triggers a flush and releases the lock, subsequent add() calls can acquire the lock before the flush thread clears the buffer, seeing size >= MAX_BEFORE_DROP and dropping spans. This results in data loss during high-throughput scenarios.
Async Redis spans are not closed when exceptions occur (sentry_sdk/integrations/redis/_async_common.py:135)
In _sentry_execute_command, spans are created via __enter__() but __exit__() is called outside of a try/finally block. If old_execute_command raises an exception, the db_span and cache_span will never be closed, causing span leaks. The sync version in _sync_common.py correctly wraps this in a try/finally block (lines 141-151).
AttributeError when legacy Span is on scope during streaming mode (sentry_sdk/scope.py:1249)
At line 1249, parent_span is assigned from self.span or self.get_current_scope().span, which can be a legacy Span (from sentry_sdk.tracing). However, at line 1284, the code accesses parent_span.segment, an attribute that only exists on StreamedSpan, not on the legacy Span class. If streaming mode is enabled but a legacy Span ends up on the scope (e.g., from a third-party integration or mixed code), this will cause an AttributeError: 'Span' object has no attribute 'segment'.
Span silently dropped when end() called without start() (sentry_sdk/traces.py:341)
When span.end() is called without first calling span.start() or using the context manager, the _context_manager_state attribute is not initialized. The code at line 342 attempts to unpack this attribute, and the resulting AttributeError is swallowed by capture_internal_exceptions(). The span is silently dropped without any warning to the user, and the scope's span reference is not restored.
Identified by Warden find-bugs
Introduce a new
start_span()API with a simpler and more intuitive signature to eventually replace the originalstart_span()andstart_transaction()APIs.Additionally, introduce a new streaming mode (
sentry_sdk.init(_experiments={"trace_lifecycle": "stream"})) that will send spans as they finish, rather than by transaction.The new API MUST be used with the new streaming mode, and the old API MUST be used in the legacy non-streaming (static) mode.
Migration guide: getsentry/sentry-docs#16072
Notes
Spanand drop the newStreamedSpanintracing.pyas a replacement.trace_id(we can't send spans from different traces in the same envelope).Release Plan
Project
https://linear.app/getsentry/project/span-first-sdk-python-727da28dd037/overview