diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index c721b56505..49eed2dedd 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -134,14 +134,30 @@ def fingerprint(self, value): """When set this overrides the default fingerprint.""" self._fingerprint = value - @_attr_setter + @property + def transaction(self): + # type: () -> Optional[Span] + """Return the transaction (root span) in the scope.""" + # XXX: update return type to Optional[Transaction] + try: + return self._span._span_recorder.spans[0] + except (AttributeError, IndexError): + return None + + @transaction.setter def transaction(self, value): # type: (Optional[str]) -> None """When set this forces a specific transaction name to be set.""" + # XXX: the docstring above is misleading. The implementation of + # apply_to_event prefers an existing value of event.transaction over + # anything set in the scope. + # XXX: note that with the introduction of the Scope.transaction getter, + # there is a semantic and type mismatch between getter and setter. The + # getter returns a transaction, the setter sets a transaction name. + # Without breaking version compatibility, we could make the setter set a + # transaction name or transaction (self._span) depending on the type of + # the value argument. self._transaction = value - span = self._span - if span: - span.transaction = value @_attr_setter def user(self, value): diff --git a/tests/test_tracing.py b/tests/test_tracing.py index 8db0f60c50..7d95f8a147 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -3,7 +3,7 @@ import pytest -from sentry_sdk import Hub, capture_message +from sentry_sdk import Hub, capture_message, start_span from sentry_sdk.tracing import Span @@ -180,3 +180,17 @@ def before_send(event, hint): pass assert len(events) == 1 + + +def test_get_transaction_from_scope(sentry_init, capture_events): + sentry_init(traces_sample_rate=1.0) + events = capture_events() + + with start_span(transaction="/"): + with start_span(op="child-span"): + with start_span(op="child-child-span"): + scope = Hub.current.scope + assert scope.span.op == "child-child-span" + assert scope.transaction.transaction == "/" + + assert len(events) == 1