Monitoring Celery beat periodic tasks
With Celery, two things can fail quietly: the beat process (which schedules periodic tasks) and the workers (which run them). If beat dies, nothing is enqueued and nothing errors. If workers are stuck, tasks pile up in the broker. Either way, your "nightly" task just doesn't happen.
Ping from the task
The simplest reliable check is a heartbeat at the end of the periodic task, because it proves that beat scheduled it and a worker ran it:
import urllib.request
from celery import shared_task
PING = "https://cronpup.com/p/REPORT-UUID"
def ping(suffix=""):
try:
urllib.request.urlopen(PING + suffix, timeout=10)
except Exception:
pass # monitoring must never break the task
@shared_task
def nightly_report():
ping("/start")
try:
build_report()
except Exception:
ping("/fail")
raise
ping()
Match the beat schedule
app.conf.beat_schedule = {
"nightly-report": {"task": "tasks.nightly_report", "schedule": crontab(hour=2, minute=30)},
}
app.conf.timezone = "UTC"
Create the CronPup monitor with the cron expression 30 2 * * * in UTC, and a grace period that
covers queue delay plus run time.
Many periodic tasks?
Use one monitor per important task, so the alert names the task that stopped. A lightweight
heartbeat task every 5 minutes also gives you an early warning that beat or the workers are down.