Skip to content

Reset DedupeIntegration's last-seen if before_send dropped the event #4142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 19, 2025
Merged
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
9 changes: 9 additions & 0 deletions sentry_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
ClientConstructor,
)
from sentry_sdk.integrations import _DEFAULT_INTEGRATIONS, setup_integrations
from sentry_sdk.integrations.dedupe import DedupeIntegration
from sentry_sdk.sessions import SessionFlusher
from sentry_sdk.envelope import Envelope
from sentry_sdk.profiler.continuous_profiler import setup_continuous_profiler
Expand Down Expand Up @@ -606,6 +607,14 @@ def _prepare_event(
self.transport.record_lost_event(
"before_send", data_category="error"
)

# If this is an exception, reset the DedupeIntegration. It still
# remembers the dropped exception as the last exception, meaning
# that if the same exception happens again and is not dropped
# in before_send, it'd get dropped by DedupeIntegration.
if event.get("exception"):
DedupeIntegration.reset_last_seen()

event = new_event

before_send_transaction = self.options["before_send_transaction"]
Expand Down
9 changes: 9 additions & 0 deletions sentry_sdk/integrations/dedupe.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,12 @@ def processor(event, hint):
return None
integration._last_seen.set(exc)
return event

@staticmethod
def reset_last_seen():
# type: () -> None
integration = sentry_sdk.get_client().get_integration(DedupeIntegration)
if integration is None:
return

integration._last_seen.set(None)
31 changes: 31 additions & 0 deletions tests/test_basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,37 @@ def test_dedupe_event_processor_drop_records_client_report(
assert lost_event_call == ("event_processor", "error", None, 1)


def test_dedupe_doesnt_take_into_account_dropped_exception(sentry_init, capture_events):
# Two exceptions happen one after another. The first one is dropped in the
# user's before_send. The second one isn't.
# Originally, DedupeIntegration would drop the second exception. This test
# is making sure that that is no longer the case -- i.e., DedupeIntegration
# doesn't consider exceptions dropped in before_send.
count = 0

def before_send(event, hint):
nonlocal count
count += 1
if count == 1:
return None
return event

sentry_init(before_send=before_send)
events = capture_events()

exc = ValueError("aha!")
for _ in range(2):
# The first ValueError will be dropped by before_send. The second
# ValueError will be accepted by before_send, and should be sent to
# Sentry.
try:
raise exc
except Exception:
capture_exception()

assert len(events) == 1


def test_event_processor_drop_records_client_report(
sentry_init, capture_events, capture_record_lost_event_calls
):
Expand Down
Loading