Skip to content

Commit d670a15

Browse files
authored
Don't set transaction status to error on sys.exit(0) (#4025)
We set transaction status to `internal_error` if there is an exception exiting the `start_transaction` context manager. We don't check what kind of exception it was. Some exceptions aren't a sign of anything wrong, like `SystemExit` with a value of 0, so we shouldn't mark the transaction as failed in that case. Closes #4024
1 parent bc72f78 commit d670a15

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed

sentry_sdk/tracing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
is_valid_sample_rate,
1212
logger,
1313
nanosecond_time,
14+
should_be_treated_as_error,
1415
)
1516

1617
from typing import TYPE_CHECKING
@@ -374,7 +375,7 @@ def __enter__(self):
374375

375376
def __exit__(self, ty, value, tb):
376377
# type: (Optional[Any], Optional[Any], Optional[Any]) -> None
377-
if value is not None:
378+
if value is not None and should_be_treated_as_error(ty, value):
378379
self.set_status(SPANSTATUS.INTERNAL_ERROR)
379380

380381
scope, old_span = self._context_manager_state

sentry_sdk/utils.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,3 +1879,12 @@ def get_current_thread_meta(thread=None):
18791879

18801880
# we've tried everything, time to give up
18811881
return None, None
1882+
1883+
1884+
def should_be_treated_as_error(ty, value):
1885+
# type: (Any, Any) -> bool
1886+
if ty == SystemExit and hasattr(value, "code") and value.code in (0, None):
1887+
# https://docs.python.org/3/library/exceptions.html#SystemExit
1888+
return False
1889+
1890+
return True

tests/tracing/test_integration_tests.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import weakref
21
import gc
2+
import random
33
import re
4+
import sys
5+
import weakref
6+
47
import pytest
5-
import random
68

79
import sentry_sdk
810
from sentry_sdk import (
@@ -297,3 +299,55 @@ def test_trace_propagation_meta_head_sdk(sentry_init):
297299
assert 'meta name="baggage"' in baggage
298300
baggage_content = re.findall('content="([^"]*)"', baggage)[0]
299301
assert baggage_content == transaction.get_baggage().serialize()
302+
303+
304+
@pytest.mark.parametrize(
305+
"exception_cls,exception_value",
306+
[
307+
(SystemExit, 0),
308+
],
309+
)
310+
def test_non_error_exceptions(
311+
sentry_init, capture_events, exception_cls, exception_value
312+
):
313+
sentry_init(traces_sample_rate=1.0)
314+
events = capture_events()
315+
316+
with start_transaction(name="hi") as transaction:
317+
transaction.set_status(SPANSTATUS.OK)
318+
with pytest.raises(exception_cls):
319+
with start_span(op="foo", name="foodesc"):
320+
raise exception_cls(exception_value)
321+
322+
assert len(events) == 1
323+
event = events[0]
324+
325+
span = event["spans"][0]
326+
assert "status" not in span.get("tags", {})
327+
assert "status" not in event["tags"]
328+
assert event["contexts"]["trace"]["status"] == "ok"
329+
330+
331+
@pytest.mark.parametrize("exception_value", [None, 0, False])
332+
def test_good_sysexit_doesnt_fail_transaction(
333+
sentry_init, capture_events, exception_value
334+
):
335+
sentry_init(traces_sample_rate=1.0)
336+
events = capture_events()
337+
338+
with start_transaction(name="hi") as transaction:
339+
transaction.set_status(SPANSTATUS.OK)
340+
with pytest.raises(SystemExit):
341+
with start_span(op="foo", name="foodesc"):
342+
if exception_value is not False:
343+
sys.exit(exception_value)
344+
else:
345+
sys.exit()
346+
347+
assert len(events) == 1
348+
event = events[0]
349+
350+
span = event["spans"][0]
351+
assert "status" not in span.get("tags", {})
352+
assert "status" not in event["tags"]
353+
assert event["contexts"]["trace"]["status"] == "ok"

0 commit comments

Comments
 (0)