> ## Documentation Index
> Fetch the complete documentation index at: https://sentrydocs.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Cron Monitoring

> Monitor scheduled jobs and get alerted when they fail or miss their schedule

Cron Monitoring watches your scheduled jobs and background tasks. Instead of only knowing a job failed (or never ran), you get visibility into every execution: when it started, how long it took, whether it succeeded, and whether it ran on time.

## How it works

Your job sends a **check-in** to Sentry when it starts and again when it finishes. Sentry compares those check-ins against the expected schedule and marks the run as ok, failed, missed, or timed out.

```
Job starts  →  send "in_progress" check-in
Job finishes →  send "ok" or "error" check-in

If no check-in arrives by the expected time → Sentry marks it as "missed"
If the "in_progress" check-in isn't closed in time → Sentry marks it as "timeout"
```

## Check-in statuses

| Status        | What it means                                                          |
| ------------- | ---------------------------------------------------------------------- |
| `in_progress` | The job sent an opening check-in and is currently running              |
| `ok`          | The job completed successfully                                         |
| `error`       | The job explicitly reported a failure                                  |
| `missed`      | No check-in arrived within the expected window                         |
| `timeout`     | The job started (`in_progress`) but didn't finish within `max_runtime` |

## Creating a monitor

<Steps>
  <Step title="Open Crons">
    In your Sentry project, navigate to **Crons** in the left sidebar.
  </Step>

  <Step title="Create a monitor">
    Click **Add Monitor**. Give it a name and a unique slug — you'll use the slug in your check-in calls.
  </Step>

  <Step title="Configure the schedule">
    Choose a schedule type and set the expression:

    * **Crontab**: a standard 5-field cron expression (e.g. `0 * * * *` for hourly)
    * **Interval**: a human-friendly interval (e.g. every 5 minutes, every 2 hours, every 1 day)

    Supported interval units: `minute`, `hour`, `day`, `week`, `month`, `year`
  </Step>

  <Step title="Set tolerances (optional)">
    * **Check-in margin** (`checkin_margin`): How many minutes after the expected time to wait before marking a run as missed. Useful for jobs that take a moment to start.
    * **Max runtime** (`max_runtime`): How many minutes a job can stay `in_progress` before Sentry marks it as timed out.
  </Step>

  <Step title="Save and instrument">
    Copy the monitor slug and add check-in calls to your job code (see below).
  </Step>
</Steps>

## Sending check-ins

### Via SDK (recommended)

The SDK handles opening and closing check-ins automatically, and reports `error` status if an exception is raised.

<CodeGroup>
  ```python Python theme={null}
  import sentry_sdk

  # Wraps the code block: sends "in_progress" on enter, "ok" on exit, "error" on exception
  with sentry_sdk.monitor(monitor_slug="my-nightly-job"):
      run_my_job()
  ```

  ```javascript JavaScript / Node.js theme={null}
  import * as Sentry from "@sentry/node";

  // Wraps the function: sends check-ins automatically
  await Sentry.withMonitor("my-nightly-job", async () => {
    await runMyJob();
  });
  ```
</CodeGroup>

### Via HTTP API

You can also send check-ins directly to the Sentry API from any language or environment that can make HTTP requests.

```bash theme={null}
# Open a check-in (job starting)
curl -X POST \
  "https://sentry.io/api/0/organizations/{org-slug}/monitors/{monitor-slug}/checkins/" \
  -H "Authorization: Bearer <your-auth-token>" \
  -H "Content-Type: application/json" \
  -d '{"status": "in_progress"}'

# Close the check-in with the returned check-in ID
curl -X PUT \
  "https://sentry.io/api/0/organizations/{org-slug}/monitors/{monitor-slug}/checkins/{checkin-id}/" \
  -H "Authorization: Bearer <your-auth-token>" \
  -H "Content-Type: application/json" \
  -d '{"status": "ok", "duration": 3200}'
```

### Via DSN (upsert)

If you'd rather not create monitors in the UI first, you can upsert a monitor directly from your check-in payload using your project DSN. Include the full monitor config in the check-in envelope:

```python Python theme={null}
import sentry_sdk

sentry_sdk.init(dsn="https://your-dsn@sentry.io/project-id")

with sentry_sdk.monitor(
    monitor_slug="my-nightly-job",
    monitor_config={
        "schedule": {"type": "crontab", "value": "0 2 * * *"},
        "checkin_margin": 5,
        "max_runtime": 30,
        "timezone": "America/New_York",
    },
):
    run_my_job()
```

<Note>
  Upsert check-ins create or update the monitor configuration automatically. This is useful when you manage monitors as code alongside your job definitions.
</Note>

## Schedule types

### Crontab

Use standard 5-field cron syntax. Sentry also supports common aliases:

| Alias                   | Equivalent  |
| ----------------------- | ----------- |
| `@yearly` / `@annually` | `0 0 1 1 *` |
| `@monthly`              | `0 0 1 * *` |
| `@weekly`               | `0 0 * * 0` |
| `@daily`                | `0 0 * * *` |
| `@hourly`               | `0 * * * *` |

### Interval

Specify a count and a unit:

```json theme={null}
{"type": "interval", "value": 5, "unit": "minute"}
{"type": "interval", "value": 2, "unit": "hour"}
{"type": "interval", "value": 1, "unit": "day"}
```

## Alerting

By default, Sentry creates an issue whenever a monitor enters a failed state (missed, error, or timeout). You can configure additional alert rules to notify your team:

* **Email** — send to specific team members or the issue assignee
* **Slack** — post to a channel
* **PagerDuty** — page on-call
* **Webhooks** — call any HTTP endpoint

Configure alert rules under **Settings > Alerts** or directly from the monitor's **Alert Rules** tab.

<Tip>
  Use the **failure\_issue\_threshold** setting to require multiple consecutive failures before an issue is created. This reduces noise from transient failures in flaky jobs.
</Tip>

## Environments

Each monitor tracks check-ins per environment. If the same job runs in `production` and `staging`, Sentry creates separate environment tracks under the same monitor. Set the environment in your check-in:

```python theme={null}
with sentry_sdk.monitor(monitor_slug="my-job", monitor_config={...}):
    # Pass environment via SDK scope
    with sentry_sdk.new_scope() as scope:
        scope.set_tag("environment", "production")
        run_my_job()
```
