Scheduled Pings

Ping patterns for Cron and Heartbeat monitors. Start + success/failure, exit-code shorthand, progress logs, and Beats accounting per pattern.

Scheduled pings are the Ping API patterns Cron and Heartbeat monitors use — anything running on a predictable schedule. The recommended shape is start at the beginning of the run plus success or failure at the end. The minimal shape is one success ping per run.

This page consolidates the older /scheduled-pings and /scheduled-job-pings references — both old URLs now resolve here.

Minimal shape — success only

One ping at the end is enough for a Cron monitor when you only need missed-run detection. Costs 1 Beat per run.

bash
/usr/bin/backup.sh
curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/success
/usr/bin/backup.sh
curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/success

If the command exits non-zero, Drumbeats does not learn about it until the next scheduled window passes without a success ping. Upgrade to the recommended shape below for explicit failure tracking.

Send start at the top of the script, then success or failure at the end. Costs 2 Beats per run, gives you duration tracking and immediate failure detection.

bash
curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/start

/usr/bin/backup.sh

if [ $? -eq 0 ]; then
  curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/success
else
  curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/failure
fi
curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/start

/usr/bin/backup.sh

if [ $? -eq 0 ]; then
  curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/success
else
  curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/failure
fi

The start ping enables three things: accurate duration tracking, DURATION_HIGH incidents on slow runs, and hung-run detection (start arrives, finish never does).

Inline crontab form

A one-liner that handles success and failure paths inside crontab itself — no wrapper script needed:

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

curl -sf suppresses curl output (-s) and treats HTTP errors as failures (-f) — important inside cron, which otherwise emails noisy curl chatter.

Exit-code shorthand

When the only branch your script needs is success vs failure, pass $? straight as the event:

bash
/usr/bin/backup.sh
curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/$?
# 0 → success, any non-zero → failure
/usr/bin/backup.sh
curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/$?
# 0 → success, any non-zero → failure

See Exit codes for the full table and concurrency-safe variants.

With progress logs

Add log events between phases of a long-running job. Each log ping costs 1 Beat and shows up on the monitor's run timeline — useful for debugging which phase failed.

bash
API="https://api.drumbeats.io/v1/ping/<monitor-id>"

curl -sf "$API/start"

pg_dump mydb > backup.sql \
  || { curl -sf "$API/failure"; exit 1; }

curl -sf -X POST "$API/log" -H "Content-Type: application/json" \
  -d '{"payload":"DB dump complete (1.2 GB)"}'

gzip backup.sql \
  || { curl -sf "$API/failure"; exit 1; }

aws s3 cp backup.sql.gz s3://backups/ \
  || { curl -sf "$API/failure"; exit 1; }

curl -sf "$API/success"
API="https://api.drumbeats.io/v1/ping/<monitor-id>"

curl -sf "$API/start"

pg_dump mydb > backup.sql \
  || { curl -sf "$API/failure"; exit 1; }

curl -sf -X POST "$API/log" -H "Content-Type: application/json" \
  -d '{"payload":"DB dump complete (1.2 GB)"}'

gzip backup.sql \
  || { curl -sf "$API/failure"; exit 1; }

aws s3 cp backup.sql.gz s3://backups/ \
  || { curl -sf "$API/failure"; exit 1; }

curl -sf "$API/success"

Reserve log pings for stages whose state you would actually want to see during triage. Routine "step finished" logs add Beats with little payoff.

Send error output on failure

When a job fails, the most useful payload is the last few lines of stderr — not the entire log file. The pattern below captures stdout + stderr, JSON-encodes it, and attaches it to the failure ping:

bash
OUTPUT=$(run-job.sh 2>&1)
EXIT=$?
if [ $EXIT -eq 0 ]; then
  curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/success
else
  curl -sf -X POST https://api.drumbeats.io/v1/ping/<monitor-id>/failure \
    -H "Content-Type: application/json" \
    -d "{\"payload\":$(echo "$OUTPUT" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}"
fi
OUTPUT=$(run-job.sh 2>&1)
EXIT=$?
if [ $EXIT -eq 0 ]; then
  curl -sf https://api.drumbeats.io/v1/ping/<monitor-id>/success
else
  curl -sf -X POST https://api.drumbeats.io/v1/ping/<monitor-id>/failure \
    -H "Content-Type: application/json" \
    -d "{\"payload\":$(echo "$OUTPUT" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}"
fi

For longer outputs, trim to the last 100 lines (tail -n 100) before posting. See Payloads for size limits and storage rules.

Status rules

The table below maps the pings Drumbeats receives to monitor state. Combined with failure_tolerance and grace_period_seconds on the monitor, this is how incidents open and close.

SituationResult
success receivedMonitor flips UP, any open incident resolves to RESOLVED.
failure receivedFailure counter +1; monitor flips DOWN once the counter reaches failure_tolerance.
start received, no finish before max_duration_secondsHung-run event, treated as a failure for incident purposes.
log receivedStored on the timeline. No status change, no incident effect.
No ping by expected_time + grace_period_secondsMISSED incident opens.
Run takes longer than max_duration_secondsDURATION_HIGH incident opens (does not flip the monitor to DOWN by default).

Tips

  • Cron monitors — what the monitor type does with these pings.
  • Heartbeat monitors — for jobs that ping continuously rather than once per scheduled run.
  • Status signals — named events vs exit-code pings, side by side.
  • Payloads — full payload reference, size limits, run_id semantics.
  • Production hardening — retries, timeouts, and how to avoid ping outages cascading into your job.