Heartbeats (cron jobs)
Ping URLs for backups and scheduled jobs, with snippets for cron, shell, Rails, Laravel, Node and Python.
How heartbeats work
A heartbeat watches something that should happen on a schedule. Instead of Pingerer checking your job, your job checks in with Pingerer: when it finishes, it requests the heartbeat's ping URL. If a ping doesn't arrive by the deadline, the heartbeat is down and you're alerted. The next ping resolves it.
- Period: how often the job runs (every 5 minutes up to weekly).
- Grace: how late a ping may be before it counts as missed, to allow for jobs that take a while.
- The deadline is the last ping (or when you created the heartbeat) plus the period plus the grace.
Ping URLs
Each heartbeat has its own URL with a secret token, shown on the Heartbeats page:
https://pingerer.com/hb/YOUR-TOKEN # success
https://pingerer.com/hb/YOUR-TOKEN/fail # the job failed: alert now
GET, POST and HEAD all work (send /fail as a GET or POST). Link previews, like Slack's when you paste the URL, aren't counted. Anyone with the URL can ping it, so treat it like a password. Pinging is limited to 30 requests a minute per heartbeat.
cron
# every night at 3am; ping only if the job succeeded
0 3 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 https://pingerer.com/hb/YOUR-TOKEN > /dev/null
Shell script
#!/bin/sh
if /usr/local/bin/backup.sh; then
curl -fsS -m 10 --retry 3 https://pingerer.com/hb/YOUR-TOKEN
else
curl -fsS -m 10 --retry 3 https://pingerer.com/hb/YOUR-TOKEN/fail
fi
Ruby on Rails
# app/jobs/nightly_backup_job.rb
require "net/http"
class NightlyBackupJob < ApplicationJob
PING = "https://pingerer.com/hb/YOUR-TOKEN"
def perform
Backup.run!
Net::HTTP.get(URI(PING))
rescue => error
Net::HTTP.get(URI("#{PING}/fail"))
raise
end
end
Laravel
// routes/console.php (or app/Console/Kernel.php)
Schedule::command('backup:run')
->daily()
->pingOnSuccess('https://pingerer.com/hb/YOUR-TOKEN')
->pingOnFailure('https://pingerer.com/hb/YOUR-TOKEN/fail');
Node.js
const PING = "https://pingerer.com/hb/YOUR-TOKEN";
async function main() {
try {
await runBackup();
await fetch(PING);
} catch (error) {
await fetch(`${PING}/fail`);
throw error;
}
}
main();
Python
import urllib.request
PING = "https://pingerer.com/hb/YOUR-TOKEN"
try:
run_backup()
urllib.request.urlopen(PING, timeout=10)
except Exception:
urllib.request.urlopen(PING + "/fail", timeout=10)
raise
From the CLI
pingerer heartbeats ping "Nightly backup"
pingerer heartbeats ping YOUR-TOKEN --fail # by token, no login needed
Tips
- Ping at the end of the job, after it really succeeded, not at the start.
- Use
curl -m 10 --retry 3so a slow network doesn't hang your job, and a blip doesn't cause a false alarm. - Set the grace to a bit more than the job's longest normal run.
- Heartbeats aren't paused by maintenance windows; pause the heartbeat itself if a job is off on purpose.
Still stuck? Contact us and a person will reply.