56
56
except ImportError :
57
57
raise DidNotEnable ("Celery not installed" )
58
58
59
+ try :
60
+ from redbeat .schedulers import RedBeatScheduler # type: ignore
61
+ except ImportError :
62
+ RedBeatScheduler = None
63
+
59
64
60
65
CELERY_CONTROL_FLOW_EXCEPTIONS = (Retry , Ignore , Reject )
61
66
@@ -76,6 +81,7 @@ def __init__(
76
81
77
82
if monitor_beat_tasks :
78
83
_patch_beat_apply_entry ()
84
+ _patch_redbeat_maybe_due ()
79
85
_setup_celery_beat_signals ()
80
86
81
87
@staticmethod
@@ -535,6 +541,62 @@ def sentry_apply_entry(*args, **kwargs):
535
541
Scheduler .apply_entry = sentry_apply_entry
536
542
537
543
544
+ def _patch_redbeat_maybe_due ():
545
+ # type: () -> None
546
+
547
+ if RedBeatScheduler is None :
548
+ return
549
+
550
+ original_maybe_due = RedBeatScheduler .maybe_due
551
+
552
+ def sentry_maybe_due (* args , ** kwargs ):
553
+ # type: (*Any, **Any) -> None
554
+ scheduler , schedule_entry = args
555
+ app = scheduler .app
556
+
557
+ celery_schedule = schedule_entry .schedule
558
+ monitor_name = schedule_entry .name
559
+
560
+ hub = Hub .current
561
+ integration = hub .get_integration (CeleryIntegration )
562
+ if integration is None :
563
+ return original_maybe_due (* args , ** kwargs )
564
+
565
+ if match_regex_list (monitor_name , integration .exclude_beat_tasks ):
566
+ return original_maybe_due (* args , ** kwargs )
567
+
568
+ with hub .configure_scope () as scope :
569
+ # When tasks are started from Celery Beat, make sure each task has its own trace.
570
+ scope .set_new_propagation_context ()
571
+
572
+ monitor_config = _get_monitor_config (celery_schedule , app , monitor_name )
573
+
574
+ is_supported_schedule = bool (monitor_config )
575
+ if is_supported_schedule :
576
+ headers = schedule_entry .options .pop ("headers" , {})
577
+ headers .update (
578
+ {
579
+ "sentry-monitor-slug" : monitor_name ,
580
+ "sentry-monitor-config" : monitor_config ,
581
+ }
582
+ )
583
+
584
+ check_in_id = capture_checkin (
585
+ monitor_slug = monitor_name ,
586
+ monitor_config = monitor_config ,
587
+ status = MonitorStatus .IN_PROGRESS ,
588
+ )
589
+ headers .update ({"sentry-monitor-check-in-id" : check_in_id })
590
+
591
+ # Set the Sentry configuration in the options of the ScheduleEntry.
592
+ # Those will be picked up in `apply_async` and added to the headers.
593
+ schedule_entry .options ["headers" ] = headers
594
+
595
+ return original_maybe_due (* args , ** kwargs )
596
+
597
+ RedBeatScheduler .maybe_due = sentry_maybe_due
598
+
599
+
538
600
def _setup_celery_beat_signals ():
539
601
# type: () -> None
540
602
task_success .connect (crons_task_success )
0 commit comments