thenpingme/laravel
Laravel package for monitoring scheduled tasks with thenping.me. It sends heartbeats for cron jobs and alerts you when tasks fail, run late, or don’t run at all, helping you catch broken schedules early.
composer require thenpingme/laravel (pin ^3.6 if you want the Laravel 11 support; ^3.5 remains valid for Laravel ≤10 on PHP 8.1).php artisan thenpingme:setup. This walks you through linking the app and writes THENPINGME_PROJECT_ID / THENPINGME_API_TOKEN into your .env. In Laravel 11 the command list is unchanged — it's still discovered via the package's service provider, so no manual registration in bootstrap/providers.php.config/thenpingme.php should now read those env values. No other wiring is required — the package listens to Laravel's scheduler events (ScheduledTaskStarting / ScheduledTaskFinished / ScheduledTaskFailed) and reports each run automatically. These event classes exist and are unchanged in Laravel 11, so the zero-config path still works.queue:work, report generation, cache warm-up). In Laravel 11 define it in routes/console.php via the Schedule facade (or your legacy Kernel on 10.x), run php artisan schedule:list to confirm it, then trigger it once (php artisan schedule:run) and verify the run appears in the thenping.me dashboard. Add an alert rule (e.g. "missing for 10 minutes") so the dead-man's switch is live.For non-Laravel work (cron scripts on other servers, container jobs, CI steps) use the manual ping command instead: php artisan thenpingme:ping "backup-database" — or hit the same ping URL with curl from any host.
Auto-monitoring the scheduler (the zero-config path). Keep the default scheduler mode. Every scheduled command that Laravel fires is reported using the command's signature or its ->name(). On the dashboard you then configure an expected cadence and grace period, and thenping.me alerts when a run is missing or failed. You don't add anything to your Kernel/routes/console.php for this — and on Laravel 11 that's especially welcome, since schedule definition moved to routes/console.php and the provider-based event listeners keep working without edits.
Naming tasks explicitly. For anything with a closure or a non-obvious signature, call ->name('nightly-invoices') so the dashboard entry is stable and readable:
// Laravel 11: routes/console.php
Schedule::call(fn () => Invoice::generate())
->dailyAt('02:00')
->name('nightly-invoices');
Manual heartbeats for external jobs. Anything not run through Laravel's scheduler (a container entrypoint, a plain crontab entry on another box, a one-off serverless function) should push a ping via thenpingme:ping <name> or a raw curl to the ping URL. This is also the pattern for "did the deploy finish?" checks in CI.
Environment separation. Create one thenping.me project per environment, and set the project ID/token per environment's .env. In local/testing, leave THENPINGME_PROJECT_ID empty so nothing is reported — this is the simplest kill switch and avoids polluting production monitors with dev runs.
Long-running / multi-server jobs. For anything using ->onOneServer() or ->withoutOverlapping(), make sure the schedule cache driver is shared (redis, database, dynamodb) so only one instance pings; the service will otherwise see duplicate runs and you won't get meaningful alerting. Laravel 11's default cache store is still database out of the box if you kept the stock skeleton — that's sufficient for single-host setups but verify it for multi-node.
Pairing with deploy and health checks. Use the manual ping after a deploy step to confirm releases complete, and use pings as a coarse liveness signal for worker pools. Combine with schedule:list in CI as a sanity check that expected tasks still exist (Laravel 11's schedule:list output includes the same names, so the check is portable across 10 → 11 upgrades).
curl pings) if the package stalls again. Check the repo's archive status before betting a year of monitoring on it.^3.5) before running composer update on a shared lockfile.lorisleiva/cron-translator. 3.6.0 moves to ^0.3. That library is only used to render human-readable cron descriptions during setup, so behaviour is cosmetic — but if another package in your app pins ^0.2, resolution will fail. Check composer why lorisleiva/cron-translator before upgrading.schedule:run is dead, no pings fire and — correctly — thenping.me flags missing runs. But that means the service can only tell you after the grace period; make sure the grace period is longer than your longest expected run time.THENPINGME_* values are read through config(), so after changing .env in production you must re-run php artisan config:cache. A token that "isn't working" is almost always stale config cache — and after a 3.5 → 3.6 upgrade do a config:clear + config:cache cycle as a matter of course.->name() detaches that task from its dashboard entry, and you get a missing-run alert rather than a clear error. Treat task names as API surface.->name() to closure-based schedules; otherwise your dashboard fills with opaque entries you can't map back to code.withoutOverlapping doesn't suppress pings. A skipped run due to overlap may still be reported or still appear "missing" depending on timing — verify what your dashboard shows for overlapping or locked tasks before relying on it.schedule:timezone or keep everything in UTC.phpunit.xml/.env.testing or fake the HTTP client so test suites don't emit pings or hit the network. 3.6.0's addition of PHP 8.3 CI is a good prompt to run your own suite against 8.2 and 8.3 before rolling out.How can I help you explore Laravel packages today?