Skip to content
Closed
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e29c09d
dedupe with a fingerprint instead of exception object
antonpirker Sep 17, 2025
2f66cd4
cleanup
antonpirker Sep 17, 2025
4e15ba1
refactor
antonpirker Sep 17, 2025
9ad77e0
refactor
antonpirker Sep 17, 2025
2b1de90
Cleanup
antonpirker Sep 17, 2025
6256765
updated test
antonpirker Sep 17, 2025
98c0bf6
updated test
antonpirker Sep 17, 2025
0c810d9
cleanup
antonpirker Sep 17, 2025
72c76c8
log message
antonpirker Sep 17, 2025
0271dc7
updated tests
antonpirker Sep 17, 2025
cbf0fc0
update tests
antonpirker Sep 18, 2025
10564dc
new test
antonpirker Sep 18, 2025
500d91a
udpate tests
antonpirker Sep 18, 2025
43b1b1d
Merge branch 'master' into antonpirker/dedupe-integration-memory-usage
antonpirker Sep 18, 2025
253e8ba
use object id
antonpirker Sep 18, 2025
560cc41
Revert "udpate tests"
antonpirker Sep 18, 2025
0c729ec
Revert "new test"
antonpirker Sep 18, 2025
149ac81
Revert "update tests"
antonpirker Sep 18, 2025
1a82df5
Revert "updated tests"
antonpirker Sep 18, 2025
d7568d5
Revert "log message"
antonpirker Sep 18, 2025
0b91f44
Revert "cleanup"
antonpirker Sep 18, 2025
c10fb5c
Revert "updated test"
antonpirker Sep 18, 2025
8c4a127
cleanup
antonpirker Sep 18, 2025
ea4a29e
cleanup
antonpirker Sep 18, 2025
cf23776
cleanup
antonpirker Sep 18, 2025
75c1ecd
cleanup
antonpirker Sep 18, 2025
04fe8ff
cleanup
antonpirker Sep 18, 2025
ce6296e
cleanup
antonpirker Sep 18, 2025
a1d0c39
cleanup
antonpirker Sep 18, 2025
9ad5133
cleanup
antonpirker Sep 18, 2025
07a3cef
Merge branch 'master' into antonpirker/dedupe-integration-memory-usage
antonpirker Sep 19, 2025
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
51 changes: 44 additions & 7 deletions sentry_sdk/integrations/dedupe.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import hashlib
import sentry_sdk
from sentry_sdk.utils import ContextVar, logger
from sentry_sdk.utils import (
ContextVar,
logger,
get_type_name,
get_type_module,
)
from sentry_sdk.integrations import Integration
from sentry_sdk.scope import add_global_event_processor

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Optional
from typing import Any, Optional

from sentry_sdk._types import Event, Hint

Expand All @@ -16,7 +22,28 @@ class DedupeIntegration(Integration):

def __init__(self):
# type: () -> None
self._last_seen = ContextVar("last-seen")
self._last_seen = ContextVar("last-seen", default=None)

def _create_exception_fingerprint(self, exc_info):
# type: (Any) -> str
"""
Creates a unique fingerprint for an exception based on type, message, and object id.
"""
exc_type, exc_value, tb = exc_info

if exc_type is None or exc_value is None:
return ""

type_module = get_type_module(exc_type) or ""
type_name = get_type_name(exc_type) or ""
exception_id = str(id(exc_value))

fingerprint_parts = [type_module, type_name, exception_id]
fingerprint_data = "||".join(fingerprint_parts).encode(
"utf-8", errors="replace"
)

return hashlib.sha256(fingerprint_data).hexdigest()

@staticmethod
def setup_once():
Expand All @@ -35,17 +62,27 @@ def processor(event, hint):
if exc_info is None:
return event

exc = exc_info[1]
if integration._last_seen.get(None) is exc:
logger.info("DedupeIntegration dropped duplicated error event %s", exc)
last_fingerprint = integration._last_seen.get()
if not last_fingerprint:
return event

fingerprint = integration._create_exception_fingerprint(exc_info)
if fingerprint == last_fingerprint:
logger.info(
"DedupeIntegration dropped duplicated error event with fingerprint %s",
fingerprint[:16],
)
return None

integration._last_seen.set(exc)
integration._last_seen.set(fingerprint)
return event

@staticmethod
def reset_last_seen():
# type: () -> None
"""
Resets the deduplication state, clearing the last seen exception fingerprint.
"""
integration = sentry_sdk.get_client().get_integration(DedupeIntegration)
if integration is None:
return
Expand Down
Loading