2020 from sentry_sdk ._types import Event , Hint
2121
2222
23- def _is_frame_in_app (namespace , abs_path , in_app_include , in_app_exclude , project_root ):
24- # type: (Any, Optional[str], Optional[List[str]], Optional[List[str]], Optional[str]) -> bool
25- return _should_be_included (
26- is_sentry_sdk_frame = False ,
27- namespace = namespace ,
28- in_app_include = in_app_include ,
29- in_app_exclude = in_app_exclude ,
30- abs_path = abs_path ,
31- project_root = project_root ,
32- )
33-
34-
35- def _create_exception_fingerprint (
36- exc_info , in_app_include , in_app_exclude , project_root
37- ):
38- # type: (Any, Optional[List[str]], Optional[List[str]], Optional[str]) -> str
39- """
40- Creates a unique fingerprint for an exception based on type, message, and in-app traceback.
41- """
42- exc_type , exc_value , tb = exc_info
43-
44- if exc_type is None or exc_value is None :
45- return ""
46-
47- type_module = get_type_module (exc_type ) or ""
48- type_name = get_type_name (exc_type ) or ""
49- message = get_error_message (exc_value )
50-
51- tb_parts = []
52- frame_count = 0
53-
54- for tb_frame in iter_stacks (tb ):
55- abs_path = _get_frame_module_abs_path (tb_frame .tb_frame ) or ""
56- namespace = tb_frame .tb_frame .f_globals .get ("__name__" )
57-
58- if not _is_frame_in_app (
59- namespace , abs_path , in_app_include , in_app_exclude , project_root
60- ):
61- continue
62-
63- file_name = abs_path .split ("/" )[- 1 ] if "/" in abs_path else abs_path
64- function_name = tb_frame .tb_frame .f_code .co_name or ""
65- line_number = str (tb_frame .tb_lineno )
66-
67- frame_fingerprint = "{}:{}:{}" .format (
68- file_name ,
69- function_name ,
70- line_number ,
71- )
72- tb_parts .append (frame_fingerprint )
73- frame_count += 1
74-
75- fingerprint_parts = [type_module , type_name , message , "|" .join (tb_parts )]
76- fingerprint_data = "||" .join (fingerprint_parts ).encode ("utf-8" , errors = "replace" )
77-
78- return hashlib .sha256 (fingerprint_data ).hexdigest ()
79-
80-
8123class DedupeIntegration (Integration ):
8224 identifier = "dedupe"
8325
8426 def __init__ (self ):
8527 # type: () -> None
8628 self ._last_fingerprint = ContextVar ("last-fingerprint" , default = None )
87-
88- self .in_app_include = None # type: Optional[List[str]]
89- self .in_app_exclude = None # type: Optional[List[str]]
29+ self .in_app_include = [] # type: List[str]
30+ self .in_app_exclude = [] # type: List[str]
9031 self .project_root = None # type: Optional[str]
9132
33+ def _is_frame_in_app (self , namespace , abs_path ):
34+ # type: (Any, Optional[str], Optional[str]) -> bool
35+ return _should_be_included (
36+ is_sentry_sdk_frame = False ,
37+ namespace = namespace ,
38+ in_app_include = self .in_app_include ,
39+ in_app_exclude = self .in_app_exclude ,
40+ abs_path = abs_path ,
41+ project_root = self .project_root ,
42+ )
43+
44+ def _create_exception_fingerprint (self , exc_info ):
45+ # type: (Any) -> str
46+ """
47+ Creates a unique fingerprint for an exception based on type, message, and in-app traceback.
48+ """
49+ exc_type , exc_value , tb = exc_info
50+
51+ if exc_type is None or exc_value is None :
52+ return ""
53+
54+ type_module = get_type_module (exc_type ) or ""
55+ type_name = get_type_name (exc_type ) or ""
56+ message = get_error_message (exc_value )
57+
58+ tb_parts = []
59+ frame_count = 0
60+
61+ for tb_frame in iter_stacks (tb ):
62+ abs_path = _get_frame_module_abs_path (tb_frame .tb_frame ) or ""
63+ namespace = tb_frame .tb_frame .f_globals .get ("__name__" )
64+
65+ if not self ._is_frame_in_app (namespace , abs_path ):
66+ continue
67+
68+ file_name = abs_path .split ("/" )[- 1 ] if "/" in abs_path else abs_path
69+ function_name = tb_frame .tb_frame .f_code .co_name or ""
70+ line_number = str (tb_frame .tb_lineno )
71+
72+ frame_fingerprint = "{}:{}:{}" .format (
73+ file_name ,
74+ function_name ,
75+ line_number ,
76+ )
77+ tb_parts .append (frame_fingerprint )
78+ frame_count += 1
79+
80+ fingerprint_parts = [type_module , type_name , message , "|" .join (tb_parts )]
81+ fingerprint_data = "||" .join (fingerprint_parts ).encode (
82+ "utf-8" , errors = "replace"
83+ )
84+
85+ return hashlib .sha256 (fingerprint_data ).hexdigest ()
86+
9287 @staticmethod
9388 def setup_once ():
9489 # type: () -> None
9590 client = sentry_sdk .get_client ()
9691 integration = client .get_integration (DedupeIntegration )
9792 if integration is not None :
98- integration .in_app_include = client .options .get ("in_app_include" )
99- integration .in_app_exclude = client .options .get ("in_app_exclude" )
100- integration .project_root = client .options .get ("project_root" )
93+ integration .in_app_include = client .options .get ("in_app_include" ) or []
94+ integration .in_app_exclude = client .options .get ("in_app_exclude" ) or []
95+ integration .project_root = client .options .get ("project_root" ) or None
10196
10297 @add_global_event_processor
10398 def processor (event , hint ):
@@ -113,19 +108,10 @@ def processor(event, hint):
113108 if exc_info is None :
114109 return event
115110
116- # Create fingerprint from exception instead of storing the object
117- fingerprint = _create_exception_fingerprint (
118- exc_info ,
119- integration .in_app_include ,
120- integration .in_app_exclude ,
121- integration .project_root ,
122- )
123- if not fingerprint :
124- return event
125-
126- # Check if this fingerprint matches the last seen one
111+ fingerprint = integration ._create_exception_fingerprint (exc_info )
127112 last_fingerprint = integration ._last_fingerprint .get ()
128- if last_fingerprint == fingerprint :
113+
114+ if fingerprint == last_fingerprint :
129115 logger .info (
130116 "DedupeIntegration dropped duplicated error event with fingerprint %s" ,
131117 fingerprint [:16 ],
0 commit comments