Cronitor’s ping URL looks like this:
https://cronitor.link/p/API_KEY/nightly-backup?state=complete
Central Logging’s looks like this:
https://logs.example.com/p/API_KEY/nightly-backup?state=complete
That is not a coincidence worth reading into — it is a shape several tools settled on. But it does mean that if you are weighing a move, the crontab edit is a hostname and one state name, not a rewrite.
This page is about whether the move is worth making, and it starts with what Cronitor does better.
Cronitor is a much broader product. Cron monitoring is one piece of it. The docs also cover synthetic website and API monitoring, heartbeat monitors, cookie-free web analytics, status pages, and team management with roles and permissions.
Central Logging has no status pages, no analytics, no synthetic checks beyond a plain HTTP GET, and one admin login with no roles at all. If more than one person needs an account, this is the wrong tool and the rest of the page will not change that.
Cronitor is hosted, and that is a feature. Someone else keeps it running, and it is watching from outside your infrastructure. A self-hosted monitor that lives on the same rack as the jobs it watches goes down with the rack. That is a real argument and it does not have a rebuttal.
Cronitor’s alerting is more configurable. It has failure tolerance for consecutive failures, schedule tolerance for missed runs, and grace periods so a job can start late without firing. Central Logging has one rule, derived automatically, and no knobs.
So: if you want a monitoring product, buy Cronitor. The case here is narrower than that.
This is a genuine design split, not a feature-list difference.
Cronitor asks you to declare the schedule. Cron syntax, an interval like every 2 hours, or a time of day like at 13:37. It knows the job should have run at 03:00 before the job has ever run once.
Central Logging works it out from the pings. It keeps the last 100 complete pings for a job, takes the median gap between them, and expects the next one at the last ping plus that median. Drift past that by more than 20% and the job is unhealthy. The check runs every minute.
Neither is strictly better.
A declared schedule is precise, and it covers the first run. Central Logging needs two completed pings before it has any idea what normal looks like; a job that has pinged once is never considered late. A job with genuinely irregular timing gives it a wobbly baseline, and there is no way to tighten the window for a job that needs it.
A learned schedule means there is nothing to keep in sync. A cron expression in a monitoring tool is a second copy of a fact that lives in your crontab, and second copies drift. A job moved from daily to hourly, with a monitor still expecting daily, is a false-alarm generator until someone remembers. Add the ping, and the monitor exists and stays correct.
If your jobs run on a regular clock, the learned approach saves configuration and cannot drift. If they are irregular, or the first missed run has to page someone, declare the schedule.
| Cronitor | Central Logging | |
|---|---|---|
| Hosting | SaaS | Self-hosted, one binary |
| Watches from | Outside your infrastructure | Your own server |
| Schedule | Declared: cron, interval or time of day | Learned from ping history |
| First-run coverage | Yes | Needs 2+ completions |
| Grace and tolerances | Failure tolerance, schedule tolerance, grace periods | 20% drift, not adjustable |
| Ping states | run, complete, fail, ok |
start, complete, fail |
| Ping methods | GET, POST, HEAD | GET, POST, HEAD |
| Message with a ping | Up to 2000 characters | Up to 500 bytes |
| Metrics with a ping | count, duration, error_count |
Any name you like, 20 per ping |
| Other ping fields | env, host, series, status_code |
status_code |
| Rate limits | 10/s per monitor, 50/s per IP, then 429 | None documented |
| Log aggregation | No | Yes |
| Uptime monitoring | Yes, synthetic checks | HTTP GET only, no status-code alerts |
| Status pages | Yes | No |
| Analytics | Yes | No |
| Teams and roles | Yes | No — one admin login |
| Pricing model | Per-monitor subscription | $187 once |
Three changes, if you decide to.
The hostname, from cronitor.link to your own server.
state=run becomes state=start. Same meaning, different word. complete and fail are the same on both.
Metric names. Cronitor’s metrics are a fixed vocabulary — count, duration, error_count. Central Logging takes any name you invent, up to twenty per ping, parsed at the last colon so the names themselves may contain colons:
curl "https://logs.example.com/p/API_KEY/nightly-backup?state=complete&status_code=0&metric=duration:418.44&metric=tables:3319&metric=bytes:9914223"
Each numeric metric gets its own chart over the last hundred runs. That is how you notice a backup getting slower months before it starts timing out.
There is no env, host or series parameter. If you were using env to separate staging from production, use distinct job names instead.
One deliberate behaviour worth knowing: a malformed metric is dropped, not rejected. The ping still succeeds. A ping is the tail of a shell command, and failing it over a typo would cause the outage it is supposed to be monitoring.
Fire only on success, so a failed job stays silent and gets caught by the missed check-in:
0 3 * * * /usr/local/bin/backup.sh && curl -fsS "https://logs.example.com/p/API_KEY/nightly-backup?state=complete"
Tell it directly when the job knows it failed. The notification goes out within a minute:
/usr/local/bin/backup.sh || curl -fsS "https://logs.example.com/p/API_KEY/nightly-backup?state=fail&status_code=$?&message=backup+failed"
A job that fails every run does not message you every run. The first failure notifies; the next stays quiet until the job completes successfully or a day has passed.
For a job that can die partway, send start first so the attempt is on record:
curl -fsS "https://logs.example.com/p/API_KEY/nightly-backup?state=start"
/usr/local/bin/backup.sh
curl -fsS "https://logs.example.com/p/API_KEY/nightly-backup?state=complete"
Ping history is kept for 90 days.
Here is what a cron monitor on its own cannot do, hosted or not.
A job fails. You get the alert. Now you want to know why — and the output of that job is somewhere else. Another tab, another login, and you are matching timestamps by hand.
Cronitor takes a 2000-character message with the ping, which is more than Central Logging’s 500 bytes, and for many jobs that is enough. For the ones where it is not, the fix is to send the output somewhere searchable:
/usr/local/bin/backup.sh 2>&1 | curl -fsS -X POST --data-binary @- \
https://logs.example.com/api/v1/ingest_logs/YOUR-SOURCE-TOKEN
Then the alert, the run history and the actual error output are one search apart, on the same clock and in the same tool. Sending logs with curl covers the error handling that stops that pipe failing quietly, and monitoring cron jobs covers the whole setup.
GET and does not alert on status codes at all.Use Cronitor if you want a hosted service watching from outside, if more than one person needs an account, if you need precise grace periods or first-run coverage, or if you want the status pages and analytics too.
Use Central Logging if you are already going to run a log server, if your jobs run on a regular clock, if one admin login is fine, and if you would rather the job’s health and the job’s output lived in the same place.
Comparing against the open-source option instead? Healthchecks.io is free to self-host and the closer comparison on price. For uptime specifically, see Uptime Kuma and Uptime Robot.
The free download is the complete product, not a trial. Point one job’s ping at it and see whether the learned schedule does what you want.
14-day refund if you buy and it does not fit.
💌 Get notified on new features and updates