Documentation

/start, /fail and duration

One ping says "I am alive". Three signals tell you when the job started, how it ended and how long it took.

Ping URL suffixes

Address Meaning Status after
/<uuid>successup
/<uuid>/startthe job startedunchanged
/<uuid>/failexplicit failuredown immediately
/<uuid>/<code>exit status 0–2550 is up, anything else is down
/<uuid>/logjournal entryunchanged

A POST body (up to 100 KB) is stored in the ping log — a handy place for the tail of a log, so an incident can be triaged without logging into the server.

A start → success pair is what gives you duration

The execution duration chart on the check page is built only from pairs: /start, then a success or an exit code. The gap between them is the runtime.

The consequence worth knowing. If you only send the success ping and never /start, the check works perfectly well — statuses, alerts and uptime are all there — but the duration chart stays empty: there is nothing to subtract. Milliseconds only exist for runs that had a start.

# no duration: the service knows it ran, not how long it took
/usr/local/bin/backup.sh && curl -fsS -m 10 "$PING"

# with duration
curl -fsS -m 10 "$PING/start"
/usr/local/bin/backup.sh
curl -fsS -m 10 "$PING/$?"

Pairs are matched in arrival order. If the job can run in several instances at once, durations blend together — such cases deserve separate checks.

Failing without the wait

The usual route to down is silence: deadline, then grace, then the alert. An explicit failure signal skips all of it — the check drops the moment the ping lands.

  • /fail — "the job reported an error";
  • /<code> — the exit status: 0 counts as success, anything else drops the check. The alert reason reads "non-zero exit status".

The second form is friendlier in a shell: the exit code of the last command already sits in $?, no branching required. In systemd the same role is played by $EXIT_STATUS inside ExecStopPost — see the snippets.

signal() { curl -fsS -m 10 --retry 3 -o /dev/null "$PING$1" || true; }

signal /start
/usr/local/bin/backup.sh
signal "/$?"

A journal entry without a status change

/log writes a line into the journal without touching the status or the deadline. Useful for milestones inside a long run: "exported 10,000 rows", "switched to the fallback source".

A first ping can create the check

Creating checks by hand is optional. Ping by slug — a readable name instead of a UUID — with ?create=1, and the check appears on first contact. Handy when jobs are rolled out by a deploy and you do not know up front how many there will be.

https://ping.cronalive.com/<ping-key>/<slug>?create=1

ping-key is the project key (Projects → Ping key in the dashboard), shared by all of its checks; slug is the job name in lower case, for example etl-run. The schedule of the new check comes from the query parameters:

Parameter Value
periodperiod in seconds, 60–31536000
gracegrace in seconds, 30–2592000
crona cron expression instead of a period
tztime zone for cron, UTC by default
tagscomma-separated tags, up to 20 × 64 characters
# a plain period
curl "https://ping.cronalive.com/<ping-key>/etl-run?create=1&period=3600&grace=300"

# a cron expression with a time zone (plus signs instead of spaces)
curl "https://ping.cronalive.com/<ping-key>/backup?create=1&cron=30+3+*+*+*&tz=Europe/Berlin"

# tags for grouping on the dashboard — comma-separated
curl "https://ping.cronalive.com/<ping-key>/etl-run?create=1&period=3600&tags=etl,prod"

Rules worth knowing in advance:

  • the call is idempotent: for an existing check create=1 and the schedule parameters are ignored — the ping simply counts. Change the schedule in the dashboard or through the API;
  • signal suffixes work here too, but they belong in the path, ahead of the query: /<ping-key>/etl-run/start?create=1;
  • with no parameters the project defaults apply (Projects → Auto-provisioning);
  • a grace below 30 seconds is raised to 30, silently, and the check is still created. Schedulers start jobs with a few seconds of jitter — waiting for CPU, for the network, surviving a daemon restart — and a grace of a few seconds turns that jitter into a stream of false down/up alerts. Refusing the ping instead would leave the job with no monitoring at all, and nobody would find out, because finding out was the monitoring's job. In the dashboard and the API, where a human is at the screen, the same value is rejected with an explicit error rather than adjusted;
  • tags are corrected, never rejected: blanks are dropped, anything over 64 characters is truncated, anything past the twentieth tag is discarded — and the check is created anyway. A label for grouping on the dashboard is not worth failing a ping over, let alone leaving a job unmonitored;
  • invalid parameters give 400, an exhausted plan check limit gives 403, disabled auto-provisioning gives 404. A broken cron or an unknown tz is still a 400 — unlike a too-small grace, there is nothing sensible to clamp them to, and guessing would create a check that waits for pings at the wrong time;
  • the ping key grants no API access and does not reveal other checks' UUIDs, but it can create checks in the project — treat it as a secret and rotate it if it leaks.

Laravel: the schedule fills itself in

The cronalive/laravel package reads the schedule off the scheduled task and sends it with the first ping, so you never retype it — and the check cannot drift away from the code:

// routes/console.php
$schedule->command('etl:run')
    ->everyFiveMinutes()
    ->pingCronaliveSlug('etl-run');

// the first ping goes out as:
// /<ping-key>/etl-run/start?create=1&cron=*%2F5+*+*+*+*&tz=UTC

// grace and tags — named arguments, the second positional one is $create:
$schedule->command('backup:run')
    ->dailyAt('03:30')->timezone('Europe/Berlin')
    ->pingCronaliveSlug('backup', graceSec: 1800, tags: ['backups', 'prod']);
  • the time zone is the task's own if it sets one, otherwise your app.timezone;
  • sub-minute tasks (everyThirtySeconds()) travel as period=60 — the shortest period the service accepts, so such a job is monitored as «pings at least once a minute»;
  • the parameters ride on all three signals, because whichever arrives first is the one that creates the check.

See also