From 0b972013e1081d073959f00721760d3e9c61895e Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 8 Sep 2026 15:15:39 +0200 Subject: [PATCH 1/3] chore: Remove transaction-based tracing from core --- MIGRATION_GUIDE.md | 1 + sentry_sdk/client.py | 26 ++++---------------------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 45caaaac79..d9c69373f1 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -150,6 +150,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh - The SDK won't set any tags on its own anymore. - The `update_current_span` API was removed. - `SanicIntegration` no longer accepts `unsampled_statuses`. +- The `trace_ignore_status_codes` option was removed. ## Deprecated diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 8c18d53831..59f02f175d 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -37,7 +37,6 @@ from sentry_sdk.sessions import SessionFlusher from sentry_sdk.traces import SpanStatus, StreamedSpan from sentry_sdk.tracing import trace -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.transport import ( AsyncHttpTransport, HttpTransportCore, @@ -363,21 +362,6 @@ def _get_options(*args: "Optional[str]", **kwargs: "Any") -> "Dict[str, Any]": env_to_bool(os.environ.get("SENTRY_KEEP_ALIVE"), strict=True) or False ) - if rv["trace_ignore_status_codes"] and has_span_streaming_enabled(rv): - logger.warning( - "The `trace_ignore_status_codes` parameter is ignored in span streaming mode.", - ) - - if rv["ignore_spans"] and not has_span_streaming_enabled(rv): - logger.warning( - "The `ignore_spans` parameter only works when `trace_lifecycle` is set to `stream`.", - ) - - if rv["before_send_span"] and not has_span_streaming_enabled(rv): - logger.warning( - "The `before_send_span` parameter only works when `trace_lifecycle` is set to `stream`.", - ) - return rv @@ -633,12 +617,10 @@ def _record_lost_event( record_lost_func=_record_lost_event, ) - self.span_batcher = None - if has_span_streaming_enabled(self.options): - self.span_batcher = SpanBatcher( - capture_func=_capture_envelope, - record_lost_func=_record_lost_event, - ) + self.span_batcher = SpanBatcher( + capture_func=_capture_envelope, + record_lost_func=_record_lost_event, + ) max_request_body_size = ("always", "never", "small", "medium") if self.options["max_request_body_size"] not in max_request_body_size: From 21fd8d94b21cf3500f04756dfc065656a894e4fc Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Thu, 10 Sep 2026 09:17:30 +0200 Subject: [PATCH 2/3] more stuff --- sentry_sdk/traces.py | 11 ---------- sentry_sdk/tracing.py | 10 +-------- sentry_sdk/tracing_utils.py | 14 ------------ tests/tracing/test_span_streaming.py | 32 ---------------------------- 4 files changed, 1 insertion(+), 66 deletions(-) diff --git a/sentry_sdk/traces.py b/sentry_sdk/traces.py index 1f96f4a383..fa9c483c96 100644 --- a/sentry_sdk/traces.py +++ b/sentry_sdk/traces.py @@ -165,17 +165,6 @@ def start_span( :return: The span that has been started. :rtype: StreamedSpan """ - from sentry_sdk.tracing_utils import has_span_streaming_enabled - - client = sentry_sdk.get_client() - if client.is_active() and not has_span_streaming_enabled(client.options): - logger.warning( - "Using span streaming API in non-span-streaming mode. Use " - "sentry_sdk.start_transaction() and sentry_sdk.start_span() " - "instead.", - ) - return NoOpStreamedSpan() - return sentry_sdk.get_current_scope().start_streamed_span( name, attributes, parent_span, active ) diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 895b2a0671..01a93987fb 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -365,14 +365,7 @@ def __repr__(self) -> str: ) def __enter__(self) -> "Span": - if has_span_streaming_enabled(sentry_sdk.get_client().options): - self._context_manager_state = None # early return sentinel - return self - - scope = self.scope or sentry_sdk.get_current_scope() - old_span = scope.span - scope.span = self - self._context_manager_state = (scope, old_span) + self._context_manager_state = None # early return sentinel return self def __exit__( @@ -1355,6 +1348,5 @@ def calculate_interest_rate(amount, rate, years): EnvironHeaders, _generate_sample_rand, extract_sentrytrace_data, - has_span_streaming_enabled, has_tracing_enabled, ) diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index 20257b070b..d7f85d9744 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -1158,13 +1158,6 @@ def span_decorator(f: "Any") -> "Any": @functools.wraps(f) async def async_wrapper(*args: "Any", **kwargs: "Any") -> "Any": - client = sentry_sdk.get_client() - if client.is_active() and not has_span_streaming_enabled(client.options): - logger.warning( - "Using span streaming API in non-span-streaming mode. Use " - "@sentry_sdk.trace instead.", - ) - span_name = name or qualname_from_function(f) or "" with start_streaming_span( @@ -1180,13 +1173,6 @@ async def async_wrapper(*args: "Any", **kwargs: "Any") -> "Any": @functools.wraps(f) def sync_wrapper(*args: "Any", **kwargs: "Any") -> "Any": - client = sentry_sdk.get_client() - if client.is_active() and not has_span_streaming_enabled(client.options): - logger.warning( - "Using span streaming API in non-span-streaming mode. Use " - "@sentry_sdk.trace instead.", - ) - span_name = name or qualname_from_function(f) or "" with start_streaming_span( diff --git a/tests/tracing/test_span_streaming.py b/tests/tracing/test_span_streaming.py index 638c3a4e83..b8fe9ec92e 100644 --- a/tests/tracing/test_span_streaming.py +++ b/tests/tracing/test_span_streaming.py @@ -12,7 +12,6 @@ SpanStatus, StreamedSpan, ) -from sentry_sdk.tracing_utils import has_span_streaming_enabled minimum_python_38 = pytest.mark.skipif( sys.version_info < (3, 8), reason="Asyncio tests need Python >= 3.8" @@ -1773,37 +1772,6 @@ def test_default_attributes(sentry_init, capture_envelopes): } -@pytest.mark.parametrize( - ("options", "expected"), - [ - ({"trace_lifecycle": "stream"}, True), - ({"_experiments": {"trace_lifecycle": "stream"}}, True), - ( - { - "trace_lifecycle": "stream", - "_experiments": {"trace_lifecycle": "static"}, - }, - True, - ), - ( - { - "trace_lifecycle": "static", - "_experiments": {"trace_lifecycle": "stream"}, - }, - False, - ), - ({"trace_lifecycle": "static"}, False), - ({"_experiments": {"trace_lifecycle": "static"}}, False), - ({}, False), - ({"_experiments": {}}, False), - ({"_experiments": None}, False), - (None, False), - ], -) -def test_has_span_streaming_enabled(options, expected): - assert has_span_streaming_enabled(options) is expected - - def test_trace_lifecycle_top_level_enables_streaming(sentry_init, capture_items): sentry_init(traces_sample_rate=1.0, trace_lifecycle="stream") From ad32db05fd0e342fed6c97c6e2d6c9c768a0c936 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Thu, 10 Sep 2026 09:22:28 +0200 Subject: [PATCH 3/3] . --- sentry_sdk/scope.py | 15 +++------------ sentry_sdk/tracing.py | 11 +++++++++-- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 76ec2cda2a..f5ff3dbb71 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -585,12 +585,9 @@ def get_traceparent(self, *args: "Any", **kwargs: "Any") -> "Optional[str]": if not has_tracing_enabled(client.options): return self.get_active_propagation_context().to_traceparent() - span_streaming = has_span_streaming_enabled(client.options) # If we have an active span, return traceparent from there - if span_streaming and self.streamed_span is not None: + if self.streamed_span is not None: return self.streamed_span._to_traceparent() - elif not span_streaming and self.span is not None: - return self.span._to_traceparent() # else return traceparent from the propagation context return self.get_active_propagation_context().to_traceparent() @@ -605,12 +602,9 @@ def get_baggage(self, *args: "Any", **kwargs: "Any") -> "Optional[Baggage]": if not has_tracing_enabled(client.options): return self.get_active_propagation_context().get_baggage() - span_streaming = has_span_streaming_enabled(client.options) # If we have an active span, return baggage from there - if span_streaming and self.streamed_span is not None: + if self.streamed_span is not None: return self.streamed_span._to_baggage() - elif not span_streaming and self.span is not None: - return self.span._to_baggage() # else return baggage from the propagation context return self.get_active_propagation_context().get_baggage() @@ -666,8 +660,7 @@ def iter_trace_propagation_headers( span = kwargs.pop("span", None) if not span: - span_streaming = has_span_streaming_enabled(client.options) - span = self.streamed_span if span_streaming else self.span + span = self.streamed_span if ( has_tracing_enabled(client.options) @@ -1415,8 +1408,6 @@ def _capture_span(self, span: "Optional[StreamedSpan]") -> None: return client = self.get_client() - if not has_span_streaming_enabled(client.options): - return merged_scope = self._merge_scopes() client._capture_span(span, scope=merged_scope) diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 01a93987fb..a3846213ef 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -365,8 +365,14 @@ def __repr__(self) -> str: ) def __enter__(self) -> "Span": - self._context_manager_state = None # early return sentinel - return self + if has_span_streaming_enabled(sentry_sdk.get_client().options): + self._context_manager_state = None # early return sentinel + return self + + scope = self.scope or sentry_sdk.get_current_scope() + old_span = scope.span + scope.span = self + self._context_manager_state = (scope, old_span) def __exit__( self, ty: "Optional[Any]", value: "Optional[Any]", tb: "Optional[Any]" @@ -1348,5 +1354,6 @@ def calculate_interest_rate(amount, rate, years): EnvironHeaders, _generate_sample_rand, extract_sentrytrace_data, + has_span_streaming_enabled, has_tracing_enabled, )