From 8b0b9300c5675c8cfda25361034b27af11b8444c Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Mon, 16 Jan 2023 12:30:30 +0100 Subject: [PATCH 1/7] Added before_send_transaction --- sentry_sdk/_types.py | 1 + sentry_sdk/client.py | 13 +++++++++++++ sentry_sdk/consts.py | 2 ++ 3 files changed, 16 insertions(+) diff --git a/sentry_sdk/_types.py b/sentry_sdk/_types.py index 3c985f21e9..7064192977 100644 --- a/sentry_sdk/_types.py +++ b/sentry_sdk/_types.py @@ -30,6 +30,7 @@ EventProcessor = Callable[[Event, Hint], Optional[Event]] ErrorProcessor = Callable[[Event, ExcInfo], Optional[Event]] BreadcrumbProcessor = Callable[[Breadcrumb, BreadcrumbHint], Optional[Breadcrumb]] + TransactionProcessor = Callable[[Event, Hint], Optional[Event]] TracesSampler = Callable[[SamplingContext], Union[float, int, bool]] diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index d32d014d96..29d2bf9784 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -248,6 +248,19 @@ def _prepare_event( ) event = new_event # type: ignore + before_send_transaction = self.options["before_send_transaction"] + if before_send_transaction is not None and event.get("type") == "transaction": + new_event = None + with capture_internal_exceptions(): + new_event = before_send_transaction(event, hint or {}) + if new_event is None: + logger.info("before send transaction dropped event (%s)", event) + if self.transport: + self.transport.record_lost_event( + "before_send_transaction", data_category="error" + ) + event = new_event # type: ignore + return event def _is_ignored_error(self, event, hint): diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index eeca4cbaf4..db50e058f4 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -20,6 +20,7 @@ Event, EventProcessor, TracesSampler, + TransactionProcessor, ) # Experiments are feature flags to enable and disable certain unstable SDK @@ -117,6 +118,7 @@ def __init__( _experiments={}, # type: Experiments # noqa: B006 proxy_headers=None, # type: Optional[Dict[str, str]] instrumenter=INSTRUMENTER.SENTRY, # type: Optional[str] + before_send_transaction=None, # type: Optional[TransactionProcessor] ): # type: (...) -> None pass From fe64837e4b9278cc8305a6a84bb36e654c260ccd Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Mon, 16 Jan 2023 12:54:41 +0100 Subject: [PATCH 2/7] Test for before_send_transaction --- tests/test_basics.py | 60 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/tests/test_basics.py b/tests/test_basics.py index 8657231fc9..0843788fe8 100644 --- a/tests/test_basics.py +++ b/tests/test_basics.py @@ -91,7 +91,65 @@ def test_event_id(sentry_init, capture_events): assert Hub.current.last_event_id() == event_id -def test_option_callback(sentry_init, capture_events, monkeypatch): +def test_option_before_send(sentry_init, capture_events, monkeypatch): + def before_send(event, hint): + event["extra"] = {"before_send_called": True} + return event + + def do_this(): + try: + raise ValueError("aha!") + except Exception: + capture_exception() + + sentry_init(before_send=before_send) + events = capture_events() + + do_this() + + (event,) = events + assert event["extra"] == {"before_send_called": True} + + sentry_init() + events = capture_events() + + do_this() + + (event,) = events + assert "before_send_called" not in event["extra"] + + +def test_option_before_send_transaction(sentry_init, capture_events, monkeypatch): + def before_send_transaction(event, hint): + assert event["type"] == "transaction" + event["extra"] = {"before_send_transaction_called": True} + return event + + sentry_init( + before_send_transaction=before_send_transaction, + traces_sample_rate=1.0, + ) + events = capture_events() + transaction = start_transaction(name="foo") + transaction.finish() + + (event,) = events + assert event["transaction"] == "foo" + assert event["extra"] == {"before_send_transaction_called": True} + + sentry_init( + traces_sample_rate=1.0, + ) + events = capture_events() + transaction = start_transaction(name="foo") + transaction.finish() + + (event,) = events + assert event["transaction"] == "foo" + assert "before_send_transaction_called" not in event["extra"] + + +def test_option_before_breadcrumb(sentry_init, capture_events, monkeypatch): drop_events = False drop_breadcrumbs = False reports = [] From 3c0aa59503e8bc77f0172cdef2a254d65afc250a Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 18 Jan 2023 14:15:58 +0100 Subject: [PATCH 3/7] Removed useless checks, because they check just the normal sdk behaviour that is already tested somewhere else. --- tests/test_basics.py | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/tests/test_basics.py b/tests/test_basics.py index 0843788fe8..e2a43729ed 100644 --- a/tests/test_basics.py +++ b/tests/test_basics.py @@ -91,7 +91,7 @@ def test_event_id(sentry_init, capture_events): assert Hub.current.last_event_id() == event_id -def test_option_before_send(sentry_init, capture_events, monkeypatch): +def test_option_before_send(sentry_init, capture_events): def before_send(event, hint): event["extra"] = {"before_send_called": True} return event @@ -110,16 +110,8 @@ def do_this(): (event,) = events assert event["extra"] == {"before_send_called": True} - sentry_init() - events = capture_events() - do_this() - - (event,) = events - assert "before_send_called" not in event["extra"] - - -def test_option_before_send_transaction(sentry_init, capture_events, monkeypatch): +def test_option_before_send_transaction(sentry_init, capture_events): def before_send_transaction(event, hint): assert event["type"] == "transaction" event["extra"] = {"before_send_transaction_called": True} @@ -137,17 +129,6 @@ def before_send_transaction(event, hint): assert event["transaction"] == "foo" assert event["extra"] == {"before_send_transaction_called": True} - sentry_init( - traces_sample_rate=1.0, - ) - events = capture_events() - transaction = start_transaction(name="foo") - transaction.finish() - - (event,) = events - assert event["transaction"] == "foo" - assert "before_send_transaction_called" not in event["extra"] - def test_option_before_breadcrumb(sentry_init, capture_events, monkeypatch): drop_events = False From a51b33759c7f4573adb25c8cd395731070cd12b1 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 18 Jan 2023 14:20:08 +0100 Subject: [PATCH 4/7] Update sentry_sdk/client.py Co-authored-by: Neel Shah --- sentry_sdk/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index f9ce980d9b..e5df64fbfb 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -257,7 +257,7 @@ def _prepare_event( logger.info("before send transaction dropped event (%s)", event) if self.transport: self.transport.record_lost_event( - "before_send_transaction", data_category="error" + "before_send", data_category="transaction" ) event = new_event # type: ignore From 763994fcdc5b3db18162fe4acd562a9e80214636 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 18 Jan 2023 14:36:38 +0100 Subject: [PATCH 5/7] Codecov should ignore tests directory --- codecov.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codecov.yml b/codecov.yml index 1989f1cd03..48df09f2bf 100644 --- a/codecov.yml +++ b/codecov.yml @@ -7,3 +7,5 @@ coverage: python: target: 90% comment: false +ignore: + - "tests" From b99d39fa437e925fe46c649c590b01491c100b8b Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 18 Jan 2023 14:49:24 +0100 Subject: [PATCH 6/7] More test coverage --- tests/test_basics.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/test_basics.py b/tests/test_basics.py index e2a43729ed..0d87e049eb 100644 --- a/tests/test_basics.py +++ b/tests/test_basics.py @@ -111,6 +111,24 @@ def do_this(): assert event["extra"] == {"before_send_called": True} +def test_option_before_send_discard(sentry_init, capture_events): + def before_send_discard(event, hint): + return None + + def do_this(): + try: + raise ValueError("aha!") + except Exception: + capture_exception() + + sentry_init(before_send=before_send_discard) + events = capture_events() + + do_this() + + assert len(events) == 0 + + def test_option_before_send_transaction(sentry_init, capture_events): def before_send_transaction(event, hint): assert event["type"] == "transaction" @@ -130,6 +148,21 @@ def before_send_transaction(event, hint): assert event["extra"] == {"before_send_transaction_called": True} +def test_option_before_send_transaction_discard(sentry_init, capture_events): + def before_send_transaction_discard(event, hint): + return None + + sentry_init( + before_send_transaction=before_send_transaction_discard, + traces_sample_rate=1.0, + ) + events = capture_events() + transaction = start_transaction(name="foo") + transaction.finish() + + assert len(events) == 0 + + def test_option_before_breadcrumb(sentry_init, capture_events, monkeypatch): drop_events = False drop_breadcrumbs = False From 578293d932755fd80c9d860b717da1b3b6a2630e Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 18 Jan 2023 15:19:08 +0100 Subject: [PATCH 7/7] Codecov should ignore _types.py because it is only type definitions for mypy (and therefore not relevant at runtime) --- codecov.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/codecov.yml b/codecov.yml index 48df09f2bf..1811996ac4 100644 --- a/codecov.yml +++ b/codecov.yml @@ -9,3 +9,4 @@ coverage: comment: false ignore: - "tests" + - "sentry_sdk/_types.py"