diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 204efae119..750113ab1f 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -24,7 +24,20 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh - The default of `traces_sample_rate` changed to `0`. Meaning: Incoming traces will be continued by default. For example, if your frontend sends a `sentry-trace/baggage` headers pair, your SDK will create Spans and send them to Sentry. (The default used to be `None` meaning by default no Spans where created, no matter what headers the frontend sent to your project.) See also: https://docs.sentry.io/platforms/python/configuration/options/#traces_sample_rate - `sentry_sdk.start_span` now only takes keyword arguments. - `sentry_sdk.start_transaction`/`sentry_sdk.start_span` no longer takes the following arguments: `span`, `parent_sampled`, `trace_id`, `span_id` or `parent_span_id`. -- `sentry_sdk.continue_trace` no longer returns a `Transaction` and is now a context manager. +- `sentry_sdk.continue_trace` no longer returns a `Transaction` and is now a context manager. + + - Use it to continue an upstream trace with the `sentry-trace` and `baggage` headers. + + ```python + headers = {"sentry-trace": "{trace_id}-{span_id}-{sampled_flag}", "baggage": "{baggage header}"} + with sentry_sdk.continue_trace(headers): + with sentry_sdk.start_span(name="continued span in trace"): + pass + ``` + + - If the headers are empty, a new trace will be started. + - If you want to force creation of a new trace, use the `sentry_sdk.new_trace` context manager. + - You can no longer change the sampled status of a span with `span.sampled = False` after starting it. The sampling decision needs to be either be made in the `traces_sampler`, or you need to pass an explicit `sampled` parameter to `start_span`. - The `Span()` constructor does not accept a `hub` parameter anymore. - `Span.finish()` does not accept a `hub` parameter anymore. @@ -227,7 +240,6 @@ 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. diff --git a/sentry_sdk/opentelemetry/scope.py b/sentry_sdk/opentelemetry/scope.py index 0202b9418e..28714c672e 100644 --- a/sentry_sdk/opentelemetry/scope.py +++ b/sentry_sdk/opentelemetry/scope.py @@ -85,7 +85,9 @@ def continue_trace( span_context = self._incoming_otel_span_context() if span_context is None: - yield + # force a new trace since no incoming stuff + with use_span(INVALID_SPAN): + yield else: with use_span(NonRecordingSpan(span_context)): yield diff --git a/tests/test_api.py b/tests/test_api.py index 02a5972380..c2aa3ae71f 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -97,6 +97,25 @@ def test_continue_trace(sentry_init): } +def test_continue_trace_without_headers_starts_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 continue_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_new_trace(sentry_init, capture_events): sentry_init(traces_sample_rate=1.0) events = capture_events()