Skip to content

Commit 0d3bc3d

Browse files
Reset DedupeIntegration's last-seen if before_send dropped the event (#4142)
Imagine an app throws an exception twice, from different places. The first exception is dropped in the user's `before_send`. The second exception is not. Should the second exception appear in Sentry? The current state is that it won't, since `DedupeIntegration` will take the first, dropped exception into account. When encountering the second exception, it'll consider it a duplicate and will drop it, even though the first exception never made it to Sentry. In this PR, we reset `DedupeIntegration`'s `last-seen` if an event has been dropped by `before_send`, ensuring that the next exception will be reported. Closes #371 --------- Co-authored-by: Anton Pirker <[email protected]>
1 parent 65132ba commit 0d3bc3d

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

sentry_sdk/client.py

+9
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
ClientConstructor,
3838
)
3939
from sentry_sdk.integrations import _DEFAULT_INTEGRATIONS, setup_integrations
40+
from sentry_sdk.integrations.dedupe import DedupeIntegration
4041
from sentry_sdk.sessions import SessionFlusher
4142
from sentry_sdk.envelope import Envelope
4243
from sentry_sdk.profiler.continuous_profiler import setup_continuous_profiler
@@ -606,6 +607,14 @@ def _prepare_event(
606607
self.transport.record_lost_event(
607608
"before_send", data_category="error"
608609
)
610+
611+
# If this is an exception, reset the DedupeIntegration. It still
612+
# remembers the dropped exception as the last exception, meaning
613+
# that if the same exception happens again and is not dropped
614+
# in before_send, it'd get dropped by DedupeIntegration.
615+
if event.get("exception"):
616+
DedupeIntegration.reset_last_seen()
617+
609618
event = new_event
610619

611620
before_send_transaction = self.options["before_send_transaction"]

sentry_sdk/integrations/dedupe.py

+9
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,12 @@ def processor(event, hint):
4040
return None
4141
integration._last_seen.set(exc)
4242
return event
43+
44+
@staticmethod
45+
def reset_last_seen():
46+
# type: () -> None
47+
integration = sentry_sdk.get_client().get_integration(DedupeIntegration)
48+
if integration is None:
49+
return
50+
51+
integration._last_seen.set(None)

tests/test_basics.py

+31
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,37 @@ def test_dedupe_event_processor_drop_records_client_report(
710710
assert lost_event_call == ("event_processor", "error", None, 1)
711711

712712

713+
def test_dedupe_doesnt_take_into_account_dropped_exception(sentry_init, capture_events):
714+
# Two exceptions happen one after another. The first one is dropped in the
715+
# user's before_send. The second one isn't.
716+
# Originally, DedupeIntegration would drop the second exception. This test
717+
# is making sure that that is no longer the case -- i.e., DedupeIntegration
718+
# doesn't consider exceptions dropped in before_send.
719+
count = 0
720+
721+
def before_send(event, hint):
722+
nonlocal count
723+
count += 1
724+
if count == 1:
725+
return None
726+
return event
727+
728+
sentry_init(before_send=before_send)
729+
events = capture_events()
730+
731+
exc = ValueError("aha!")
732+
for _ in range(2):
733+
# The first ValueError will be dropped by before_send. The second
734+
# ValueError will be accepted by before_send, and should be sent to
735+
# Sentry.
736+
try:
737+
raise exc
738+
except Exception:
739+
capture_exception()
740+
741+
assert len(events) == 1
742+
743+
713744
def test_event_processor_drop_records_client_report(
714745
sentry_init, capture_events, capture_record_lost_event_calls
715746
):

0 commit comments

Comments
 (0)