diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 9cc8a14fa1..0cc375b4bd 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -182,6 +182,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh ### Deprecated - `sentry_sdk.start_transaction()` is deprecated. Use `sentry_sdk.start_span()` instead. + - If you want to force creation of a new trace, use the `sentry_sdk.new_trace()` context manager. - `Span.set_data()` is deprecated. Use `Span.set_attribute()` instead. ## Upgrading to 2.0 diff --git a/sentry_sdk/__init__.py b/sentry_sdk/__init__.py index a900f73c0b..708433fe08 100644 --- a/sentry_sdk/__init__.py +++ b/sentry_sdk/__init__.py @@ -22,6 +22,7 @@ "capture_exception", "capture_message", "continue_trace", + "new_trace", "flush", "get_baggage", "get_client", diff --git a/sentry_sdk/api.py b/sentry_sdk/api.py index 3aefc57f69..9b9b57704a 100644 --- a/sentry_sdk/api.py +++ b/sentry_sdk/api.py @@ -48,6 +48,7 @@ "capture_exception", "capture_message", "continue_trace", + "new_trace", "flush", "get_baggage", "get_client", @@ -315,6 +316,15 @@ def continue_trace(environ_or_headers: dict[str, Any]) -> Generator[None, None, yield +@contextmanager +def new_trace() -> Generator[None, None, None]: + """ + Force creation of a new trace. + """ + with get_isolation_scope().new_trace(): + yield + + @scopemethod def start_session( session_mode: str = "application", diff --git a/sentry_sdk/opentelemetry/scope.py b/sentry_sdk/opentelemetry/scope.py index ec398093c7..0202b9418e 100644 --- a/sentry_sdk/opentelemetry/scope.py +++ b/sentry_sdk/opentelemetry/scope.py @@ -15,6 +15,7 @@ TraceFlags, TraceState, use_span, + INVALID_SPAN, ) from sentry_sdk.opentelemetry.consts import ( @@ -89,6 +90,15 @@ def continue_trace( with use_span(NonRecordingSpan(span_context)): yield + @contextmanager + def new_trace(self) -> Generator[None, None, None]: + """ + Force creation of a new trace. + """ + self.generate_propagation_context() + with use_span(INVALID_SPAN): + yield + def _incoming_otel_span_context(self) -> Optional[SpanContext]: if self._propagation_context is None: return None diff --git a/tests/test_api.py b/tests/test_api.py index 0004c56662..02a5972380 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -5,6 +5,7 @@ from sentry_sdk import ( capture_exception, continue_trace, + new_trace, get_baggage, get_client, get_current_span, @@ -96,6 +97,25 @@ def test_continue_trace(sentry_init): } +def test_new_trace(sentry_init, capture_events): + sentry_init(traces_sample_rate=1.0) + events = capture_events() + + with start_span(name="parent"): + with start_span(name="child"): + with new_trace(): + with start_span(name="parent2"): + with start_span(name="child2"): + pass + + assert len(events) == 2 + (tx1, tx2) = events + assert tx1["transaction"] == "parent2" + assert tx1["spans"][0]["description"] == "child2" + assert tx2["transaction"] == "parent" + assert tx2["spans"][0]["description"] == "child" + + def test_is_initialized(): assert not is_initialized()