Cron monitors

How Drumbeats watches scheduled jobs. Cron expression, timezone, grace period, ping wiring, missed-run detection, and failure handling.

A Cron monitor watches a job that runs on a fixed schedule. Drumbeats computes the next expected run from your cron expression, timezone, and grace period, then opens an incident when that run does not report success in time.

Use a Cron monitor when a scheduler (system cron, Kubernetes CronJob, Airflow, GitLab schedule, Render Cron Job) drives the work on a known timetable.

Configuration

FieldRequiredExampleDescription
cron_expression0 2 *Standard five-field cron. Six-field (with seconds) is not supported.
timezoneEurope/AmsterdamAny IANA timezone. The schedule is interpreted in this zone.
grace_period_seconds300How long Drumbeats waits past the scheduled time before declaring the run missed. Default 5 minutes.
failure_tolerance1Consecutive failures before the monitor flips to DOWN. Default 1.
max_duration_seconds1800If a start ping is not followed by success or failure within this window, Drumbeats records a hung run.

Wire pings into your cron job

The minimal pattern wraps your job command with a single success/failure ping:

bash
0 2 * * * /usr/bin/backup.sh \
  && curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/success \
  || curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/failure
0 2 * * * /usr/bin/backup.sh \
  && curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/success \
  || curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/failure

If you also want duration tracking and stdout capture, send a start ping first and POST the output with the final event:

bash
RUN_ID="backup-$(date +%s)"
API="https://api.drumbeats.io/v1/ping/<monitor-id>"

curl -sf "$API/start?run_id=$RUN_ID"

OUTPUT=$(/usr/bin/backup.sh 2>&1)
STATUS=$?

if [ $STATUS -eq 0 ]; then
  curl -sf -X POST "$API/success?run_id=$RUN_ID" \
    -H "Content-Type: application/json" \
    -d "$(jq -n --arg p "$OUTPUT" '{payload: $p}')"
else
  curl -sf -X POST "$API/failure?run_id=$RUN_ID" \
    -H "Content-Type: application/json" \
    -d "$(jq -n --arg p "$OUTPUT" '{payload: $p}')"
fi
RUN_ID="backup-$(date +%s)"
API="https://api.drumbeats.io/v1/ping/<monitor-id>"

curl -sf "$API/start?run_id=$RUN_ID"

OUTPUT=$(/usr/bin/backup.sh 2>&1)
STATUS=$?

if [ $STATUS -eq 0 ]; then
  curl -sf -X POST "$API/success?run_id=$RUN_ID" \
    -H "Content-Type: application/json" \
    -d "$(jq -n --arg p "$OUTPUT" '{payload: $p}')"
else
  curl -sf -X POST "$API/failure?run_id=$RUN_ID" \
    -H "Content-Type: application/json" \
    -d "$(jq -n --arg p "$OUTPUT" '{payload: $p}')"
fi

The run_id is optional for Cron monitors but recommended — it makes hung-run detection precise and lets you replay the run's stdout from the dashboard.

Alert behaviour

A Cron monitor opens an incident on three signals:

  • MISSED. The scheduled time + grace period passes without a success ping. The monitor flips to DOWN immediately.
  • FAILED. Drumbeats receives a failure ping (or a non-zero exit code via /v1/ping/.../{code}). The monitor flips to DOWN after failure_tolerance consecutive failures.
  • DURATION_HIGH / DURATION_LOW. The run finishes outside the recorded baseline (see duration assertions). These are warnings, not DOWN events, by default.

Recovery is automatic: a success ping inside the next expected window resolves the incident and flips the monitor back to UP.

Common patterns

Skip pings when the job is short-circuited

If your job sometimes legitimately decides not to run (e.g. flag-gated), do not skip the ping — send success with a payload describing the decision so the schedule stays satisfied:

bash
if should_skip; then
  curl -sf -X POST "$API/success?run_id=$RUN_ID" \
    -H "Content-Type: application/json" \
    -d '{"payload": "skipped: feature-flag off"}'
  exit 0
fi
if should_skip; then
  curl -sf -X POST "$API/success?run_id=$RUN_ID" \
    -H "Content-Type: application/json" \
    -d '{"payload": "skipped: feature-flag off"}'
  exit 0
fi

Cron jobs that span timezone shifts (DST)

The monitor's timezone field handles daylight-saving transitions correctly. 0 2 * in Europe/Amsterdam is 02:00 local time year-round — Drumbeats follows the transition.

Multiple cron entries pinging one monitor

A single monitor can be pinged from multiple schedules — the next-expected-run logic uses whichever cron line ran most recently. For independent schedules, prefer one monitor per cron entry; the dashboard surfaces each one separately.