22
33import sys
44
5- from celery .signals import task_failure , task_prerun , task_postrun
65from celery .exceptions import SoftTimeLimitExceeded
76
87from sentry_sdk .hub import Hub
98from sentry_sdk .utils import capture_internal_exceptions , event_from_exception
9+ from sentry_sdk ._compat import reraise
1010from sentry_sdk .integrations import Integration
1111from sentry_sdk .integrations .logging import ignore_logger
1212
@@ -16,33 +16,42 @@ class CeleryIntegration(Integration):
1616
1717 @staticmethod
1818 def setup_once ():
19- task_prerun .connect (_handle_task_prerun , weak = False )
20- task_postrun .connect (_handle_task_postrun , weak = False )
21- task_failure .connect (_process_failure_signal , weak = False )
19+ import celery .app .trace as trace
20+
21+ old_build_tracer = trace .build_tracer
22+
23+ def sentry_build_tracer (name , task , * args , ** kwargs ):
24+ task .__call__ = _wrap_task_call (task , task .__call__ )
25+ task .run = _wrap_task_call (task , task .run )
26+ return old_build_tracer (name , task , * args , ** kwargs )
27+
28+ trace .build_tracer = sentry_build_tracer
2229
2330 # This logger logs every status of every task that ran on the worker.
2431 # Meaning that every task's breadcrumbs are full of stuff like "Task
2532 # <foo> raised unexpected <bar>".
2633 ignore_logger ("celery.worker.job" )
2734
2835
29- def _process_failure_signal (sender , task_id , einfo , ** kw ):
30- # einfo from celery is not reliable
31- exc_info = sys .exc_info ()
32-
33- hub = Hub .current
34- integration = hub .get_integration (CeleryIntegration )
35- if integration is None :
36- return
36+ def _wrap_task_call (self , f ):
37+ def _inner (* args , ** kwargs ):
38+ hub = Hub .current
39+ if hub .get_integration (CeleryIntegration ) is None :
40+ return f (* args , ** kwargs )
3741
38- _capture_event (hub , exc_info )
42+ with hub .configure_scope () as scope :
43+ if scope ._name == "celery" :
44+ return f (* args , ** kwargs )
3945
46+ with hub .push_scope () as scope :
47+ scope ._name = "celery"
48+ scope .add_event_processor (_make_event_processor (args , kwargs , self ))
49+ try :
50+ return f (* args , ** kwargs )
51+ except Exception :
52+ reraise (* _capture_exception (hub ))
4053
41- def _handle_task_prerun (sender , task , args , kwargs , ** _ ):
42- hub = Hub .current
43- if hub .get_integration (CeleryIntegration ) is not None :
44- scope = hub .push_scope ().__enter__ ()
45- scope .add_event_processor (_make_event_processor (args , kwargs , task ))
54+ return _inner
4655
4756
4857def _make_event_processor (args , kwargs , task ):
@@ -78,16 +87,12 @@ def event_processor(event, hint):
7887 return event_processor
7988
8089
81- def _handle_task_postrun (sender , task_id , task , ** kw ):
82- hub = Hub .current
83- if hub .get_integration (CeleryIntegration ) is not None :
84- hub .pop_scope_unsafe ()
85-
86-
87- def _capture_event (hub , exc_info ):
90+ def _capture_exception (hub ):
91+ exc_info = sys .exc_info ()
8892 event , hint = event_from_exception (
8993 exc_info ,
9094 client_options = hub .client .options ,
9195 mechanism = {"type" : "celery" , "handled" : False },
9296 )
9397 hub .capture_event (event , hint = hint )
98+ return exc_info
0 commit comments