Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions sentry_sdk/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,12 @@ def span(self, span: "Optional[Span]") -> None:
self._transaction = transaction.name
if transaction.source:
self._transaction_info["source"] = transaction.source
elif span is None:
self._transaction = None
Comment thread
cursor[bot] marked this conversation as resolved.
Resolved
# The transaction source describes the transaction name; leaving
# it behind would stamp stale transaction_info on later events
# that no longer carry a transaction.
self._transaction_info = {}

@property
def streamed_span(self) -> "Optional[StreamedSpan]":
Expand Down
42 changes: 42 additions & 0 deletions tests/test_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -1110,3 +1110,45 @@ def test_conversation_id_clear():

scope.clear()
assert scope.get_conversation_id() is None


def test_transaction_name_cleared_when_span_unset():
"""Scope._transaction follows the span lifecycle (GH-7774).

Set by a Transaction, preserved while a child span is active, cleared
when the span is set back to None (top-level transaction exit).
"""
from sentry_sdk.tracing import Transaction

scope = Scope()

transaction = Transaction(name="my-transaction")
scope.span = transaction
assert scope._transaction == "my-transaction"
assert scope._transaction_info.get("source") # info follows the name

child = transaction.start_child(op="child")
scope.span = child
assert scope._transaction == "my-transaction"

scope.span = None
assert scope._transaction is None
assert scope._transaction_info == {} # no stale source left behind


def test_transaction_name_survives_nested_span_exit():
"""Exiting a child span restores the transaction on the scope.

The transaction name must not be dropped when an inner span finishes
while the transaction is still live.
"""
scope = Scope()

with sentry_sdk.start_transaction(name="my-transaction", scope=scope):
assert scope._transaction == "my-transaction"
with sentry_sdk.start_span(op="child", scope=scope):
assert scope._transaction == "my-transaction"
# span restored to the transaction, not None
assert scope._transaction == "my-transaction"

assert scope._transaction is None