# Monitor scheduled tasks

> Lampwick learns each scheduled task's cron from its runs and alerts when a task misses a run, starts failing or runs longer than you allow.

**Schedule health** shows when each scheduled task should run next and whether it did. Lampwick learns the schedule from the runs your app reports, so a task appears after its first run without any setup.

## Requirements

- The [Laravel package](/docs/laravel/) with the agent running (`php artisan lampwick:agent`).
- `LAMPWICK_SCHEDULED_TASK_SAMPLE_RATE` at `1` (the default): missed-run alerts need every run.
- At most 500 tasks per project.

## Check that it works

1. Open the project and go to **Schedule health** in the sidebar (under **Executions**, after **Scheduled tasks**).
2. After the scheduler runs, each task shows its cron in words ("every 30 seconds" for sub-minute tasks), **Last run**, **Next run** and a **Status**.

| Status | Meaning |
|---|---|
| **On time** | The last run came when expected. |
| **Late** | Past its expected run, still within the grace period. |
| **Missed** | Past the grace period. The team was alerted. |
| **Failing** | The latest run failed. |
| **Unknown schedule** | The expression never matches within 5 years, such as `0 0 31 2 *`. It never alerts. |
| **Muted** | You muted its alerts. |

The next run comes from the cron expression, the timezone (an IANA name or an offset such as `+02:00`) and `repeat_seconds`, with the Laravel scheduler's daylight saving behavior. A `skipped` run counts as a run.

## Alerts

Every alert goes to the whole team by push notification and e-mail ([alerts](/docs/alerts/)).

| Alert | When |
|---|---|
| **Missed: TASK** | No run within the grace period after the expected time. One alert, then nothing until it runs again. |
| **Running again: TASK** | It runs again after a missed-run alert. |
| **Failed: TASK** | A task starts failing, at most once per hour per task, not on every failed run. Without an exception, the alert says none was recorded: check the exit code. |
| **Slow: TASK** | A run takes longer than the task's duration alert. At most once per hour. |
| **No data** or **Scheduler not running** | The project sends nothing at all, or no task ran while at least 2 missed. One alert for the project instead of one per task. It asks whether the app is in maintenance mode (`php artisan down`). |
| **Rescheduled: TASK (ignore the earlier alert)** | A task that alerted now runs on a new schedule. |

### The grace period

A run is missed when it hasn't come by the expected time plus a margin. The margin is at least 5 minutes, or a fifth of the interval (up to an hour) when that is longer, plus 1.5 times the task's longest run of the last week, plus the runs of the project's other tasks due at the same time, since `schedule:run` runs them one after another. For 5 minutes after Lampwick restarts, it reports no missed runs.

## Set a duration alert, mute or forget a task

Next to each task on **Schedule health**:

- The duration select: **No duration alert** (the default), or **Alert if longer than 5 min** up to 480 min. Not for tasks with `runInBackground`, which only report their start.
- **Mute** stops alerts for the task; **Unmute** turns them back on.
- **Forget** stops expecting the task until it runs again.

A task removed from your schedule shows **Missed** and is forgotten after 7 days. A task that was clearly replaced (same name with another cron or timezone, or renamed) is forgotten at once, without an alert.

In the API: `listSchedules`, `updateSchedule` (`muted`, `max_runtime_minutes` up to 1440; `0` turns the duration alert off) and `deleteSchedule` to forget.

## Troubleshooting

| What you see | Cause and fix |
|---|---|
| "No scheduled tasks yet" | No task has run since the package was installed. Check that the agent runs and that `schedule:run` is in your server's crontab. |
| A task shows **Missed** but did run | `LAMPWICK_SCHEDULED_TASK_SAMPLE_RATE` is below 1, so some runs aren't sent. Set it to `1`. |
| **Scheduler not running** after a deploy | The app is in maintenance mode, or the cron entry for `schedule:run` is gone. |
| A task you deleted still shows **Missed** | Click **Forget**, or wait 7 days. |
| "This project has 500 scheduled tasks, the maximum" | A new task is only tracked when it can replace the task that has been missing longest. Forget tasks you no longer run. |
