Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 92 additions & 158 deletions docs/platforms/javascript/common/crons/index.mdx
Original file line number Diff line number Diff line change
@@ -1,242 +1,176 @@
---
title: Set Up Crons
sidebar_title: Crons
description: "Sentry Crons allows you to monitor the uptime and performance of any scheduled, recurring job in your application using the Sentry JavaScript SDK."
description: "Monitor scheduled JavaScript jobs with automatic cron instrumentation or manual check-ins, depending on your server runtime and framework."
sidebar_order: 9
sidebar_section: features
supportedCategories:
- server
---

Once implemented, it'll allow you to get alerts and metrics to help you solve errors, detect timeouts, and prevent disruptions to your service.
Sentry Crons monitors scheduled, recurring jobs and alerts you when a job fails, takes too long, or doesn't run when expected.

<PlatformSection supported={['javascript.nextjs', 'javascript.sveltekit', 'javascript.remix', 'javascript.astro', 'javascript.bun', 'javascript.deno', 'javascript.cloudflare', 'javascript.node', 'javascript.aws-lambda', 'javascript.azure-functions', 'javascript.express', "javascript.fastify", 'javascript.gcp-functions', 'javascript.hapi', 'javascript.hono', 'javascript.koa', 'javascript.nestjs', 'javascript.tanstackstart-react']}>
<PlatformCategorySection supported={["server"]}>
Comment thread
sentry-junior[bot] marked this conversation as resolved.
Outdated

## Requirements

<PlatformContent includePath="crons/requirements" />
<PlatformCategorySection supported={["browser"]}>
Comment thread
sentry-junior[bot] marked this conversation as resolved.
Outdated

<PlatformContent includePath="crons/setup" />
Cron monitoring runs on the server, not in browser code. Add the instrumentation below where your scheduled job executes.

</PlatformSection>

<PlatformSection notSupported={['javascript.nextjs', 'javascript.sveltekit', 'javascript.remix', 'javascript.astro', 'javascript.bun', 'javascript.deno', 'javascript.cloudflare', 'javascript.node', 'javascript.aws-lambda', 'javascript.azure-functions', 'javascript.express', 'javascript.fastify', 'javascript.gcp-functions', 'javascript.hapi', 'javascript.hono', 'javascript.koa', 'javascript.nestjs', 'javascript.tanstackstart-react']}>
</PlatformCategorySection>

## Requirements

To begin monitoring your recurring, scheduled job:

1. [Create a new monitor](https://sentry.io/issues/alerts/new/crons/) in Sentry.
2. Configure check-ins or a heartbeat for your job.

Optionally, you can skip the first step and [create or update (upsert) a monitor through a check-in](#creating-or-updating-a-monitor-through-a-check-in-optional). See more below.

## Check-Ins (Recommended)

Check-in monitoring allows you to track a job's progress by completing two check-ins: one at the start of your job and another at the end of your job. This two-step process allows Sentry to notify you if your job didn't start when expected (missed) or if it exceeded its maximum runtime (failed).
<PlatformContent includePath="crons/requirements" />

```bash {tabTitle: cURL}
SENTRY_INGEST="https://___ORG_INGEST_DOMAIN___"
SENTRY_CRONS="${SENTRY_INGEST}/api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/"
You can also [create or update a monitor in code](#upserting-cron-monitors) instead of creating it in Sentry first.

# 🟡 Notify Sentry your job is running:
curl "${SENTRY_CRONS}?status=in_progress"
Use automatic instrumentation when it supports your scheduler. Otherwise, wrap each job execution with [`Sentry.withMonitor`](#job-monitoring), or send [`Sentry.captureCheckIn`](#check-ins) calls yourself. These APIs work independently of the scheduler and are the fallback for jobs without automatic instrumentation.

# Execute your scheduled task here...
Use one monitoring approach per job to avoid duplicate check-ins. Import `Sentry` from the SDK you initialized for the job's runtime.

# 🟢 Notify Sentry your job has completed successfully:
curl "${SENTRY_CRONS}?status=ok"
```
<PlatformSection supported={["javascript.hono"]}>

```http {tabTitle: HTTP}
GET /api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/?status=in_progress HTTP/1.1
Host: ___ORG_INGEST_DOMAIN___
Use a runtime-specific import: `@sentry/hono/node`, `@sentry/hono/bun`, `@sentry/hono/deno`, or `@sentry/hono/cloudflare`. The root `@sentry/hono` entry point doesn't export the monitoring APIs. Initialize the runtime SDK for the scheduled job; Hono's request middleware alone doesn't initialize jobs that run outside an HTTP request.

GET /api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/?status=ok HTTP/1.1
Host: ___ORG_INGEST_DOMAIN___
```
- **Node.js and Bun:** Use the cron library wrappers below.
Comment thread
sentry-junior[bot] marked this conversation as resolved.
Outdated
- **Deno:** Use the opt-in [DenoCron integration](/platforms/javascript/guides/deno/crons/#automatic-check-ins-with-denocron), subject to its Deno version requirements.
- **Cloudflare Workers:** Scheduled-handler tracing doesn't send check-ins. Use `withMonitor` or `captureCheckIn`, as shown in the [Cloudflare guide](/platforms/javascript/guides/cloudflare/crons/#cloudflare-scheduled-handlers).

If your job execution fails:

```bash {tabTitle: cURL}
# 🔴 Notify Sentry your job has failed:
curl "${SENTRY_CRONS}?status=error"
```

```http {tabTitle: HTTP}
GET /api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/?status=error HTTP/1.1
Host: ___ORG_INGEST_DOMAIN___
```
</PlatformSection>

<Alert>
<PlatformSection supported={["javascript.react-router"]}>

If you expect your scheduled jobs to overlap, read about [Overlapping Jobs](#overlapping-jobs-optional) below.
For Cloudflare Workers, use the initialized `@sentry/cloudflare` SDK for check-ins. The `@sentry/react-router/cloudflare` entry point doesn't export `withMonitor` or `captureCheckIn`.

</Alert>
</PlatformSection>

### Specifying monitor environments (Optional)
<PlatformSection supported={["javascript.deno"]}>

When sending check-ins to your monitor you may specify the `environment` of the
check-in. This allows you to monitor a single schedule across multiple
environments.
## Automatic Check-Ins With `Deno.cron`

If you don't specify an environment with your check-ins the default is `production`.
The opt-in `denoCronIntegration` wraps `Deno.cron` callbacks with `withMonitor`, using the job name as the monitor slug and the cron schedule to create or update the monitor. It isn't enabled by default.

<Alert>
<Alert level="warning">

Monitor environments are still early in development. Currently, after a check-in
occurs for a specific environment, you must continue sending check-ins on
schedule or delete the monitor environment; otherwise, it will be marked as missed.
The `DenoCron` integration does not work on Deno 2.9.0 and later. On these versions `Deno.cron` is a read-only property, so `Sentry.init` stops with `TypeError: Cannot set property cron of #<Object> which has only a getter` and your app does not start. Use `Sentry.withMonitor` or `Sentry.captureCheckIn` instead.

</Alert>

```bash {tabTitle: cURL}
SENTRY_INGEST="https://___ORG_INGEST_DOMAIN___"
SENTRY_CRONS="${SENTRY_INGEST}/api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/"

# 🟡 Notify Sentry your job is running in the dev environment:
curl "${SENTRY_CRONS}?environment=dev&status=in_progress"
Requires SDK version `7.88.0` or higher and Deno `2.8.3` or earlier. Add the integration before registering your jobs:

# Execute your scheduled task here...
```typescript
import * as Sentry from "___SDK_PACKAGE___";

# 🟢 Notify Sentry your dev environment job has completed successfully:
curl "${SENTRY_CRONS}?environment=dev&status=ok"
```

### Creating or Updating a Monitor Through a Check-In (Optional)

Sentry enables the automatic creation or update of a monitor (upsert) through the check-in payload. This can be useful if you have many scheduled tasks or need to create them dynamically.

```bash {tabTitle: cURL}
SENTRY_INGEST="https://___ORG_INGEST_DOMAIN___"
SENTRY_CRONS="${SENTRY_INGEST}/api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/"

# 🟡 Notify Sentry your job is running:
curl -X POST "${SENTRY_CRONS}" \
--header 'Content-Type: application/json' \
--data-raw '{"monitor_config": {"schedule": {"type": "crontab", "value": "0 * * * *"}}, "status": "in_progress"}'
```
Sentry.init({
dsn: "___PUBLIC_DSN___",
integrations: [Sentry.denoCronIntegration()],
});

```http {tabTitle: HTTP}
POST /api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/ HTTP/1.1
Host: ___ORG_INGEST_DOMAIN___
Content-Type: application/json

{
"monitor_config": {
"schedule": {"type": "crontab", "value": "0 * * * *"},
"checkin_margin": 1,
"max_runtime": 20,
"timezone": "America/Los_Angeles"
},
"status": "in_progress"
}
Deno.cron("my-cron-job", "* * * * *", async () => {
// Execute your scheduled task here.
});
```

Monitor `monitor_config` parameters:
</PlatformSection>

`schedule_type`:
<PlatformSection supported={["javascript.nextjs"]}>

The schedule representation for your monitor, either `crontab` or `interval`.
## Automatic Check-Ins (Vercel Only)

`schedule`:
For [Vercel Cron Jobs](https://vercel.com/docs/cron-jobs) running in the Node.js runtime, enable `_experimental.vercelCronsMonitoring` in `withSentryConfig`. The SDK reads the `crons` entries in `vercel.json` at build time and emits check-ins from matching cron request spans at runtime. This works with both the App Router and Pages Router, and both Turbopack and Webpack.

The job's schedule :
```typescript {filename:next.config.ts}
import { withSentryConfig } from "@sentry/nextjs/config";

This is an object specifying a `schedule_type` of either `crontab` or `interval`. The structure will vary depending on the type:
const nextConfig = {};

```json
{"type": "crontab", "value": "0 * * * *"}
{"type": "interval", "value": 2, "unit": "hour"}
export default withSentryConfig(nextConfig, {
_experimental: {
vercelCronsMonitoring: true,
},
});
```

`checkin_margin`:

The amount of time (in minutes) Sentry should wait for your check-in before it's considered missed ("grace period"). Optional.

<Alert>

We recommend that your check-in margin be less than or equal to your interval.
This option is experimental. The older `webpack.automaticVercelMonitors` option only works with Webpack and the Pages Router. If both options are enabled, the SDK uses the experimental span-based approach.

</Alert>

`max_runtime`:
See <PlatformLink to="/manual-setup/pages-router/#vercel-cron-jobs-optional">Vercel Cron Jobs setup</PlatformLink> for details. For Edge runtime jobs or other schedulers without automatic monitoring, use `withMonitor` or `captureCheckIn` in the job handler.

The amount of time (in minutes) your job is allowed to run before it's considered failed. Optional.
</PlatformSection>

`failure_issue_threshold`:
<PlatformSection supported={["javascript.nestjs"]}>

The number of consecutive failed check-ins it takes before an issue is created. Optional.
## Automatic Check-Ins With NestJS

`recovery_threshold`:
Jobs scheduled with `@nestjs/schedule`'s `@Cron` decorator alone don't send check-ins to Sentry. Add `@SentryCron` to monitor each invocation:

The number of consecutive OK check-ins it takes before an issue is resolved. Optional.
<Include name="nestjs-sentry-cron-decorator.mdx" />

`timezone`
</PlatformSection>

The `tz` where your job is running. This is usually your server's timezone, (such as `America/Los_Angeles`). See [list of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Optional.
<PlatformSection supported={["javascript.cloudflare"]}>

<Alert level="warning">
## Cloudflare Scheduled Handlers

It's important to provide a timezone for non-repeating crontab schedules, such as `0 17 * * *` (every day at 5pm).
The Cloudflare SDK instruments `scheduled` handlers for tracing and error capture, but doesn't automatically send cron check-ins or create monitors. A scheduled-handler span isn't a cron check-in.

</Alert>
Inside a worker instrumented with `Sentry.withSentry`, wrap the scheduled task with `withMonitor`:

### Overlapping Jobs (Optional)
```typescript
import * as Sentry from "@sentry/cloudflare";

A job execution that begins before the previous job execution has been completed is called an overlapping job. This happens if you have a job with a runtime duration longer than your job's interval schedule.
export default Sentry.withSentry(() => ({ dsn: "___PUBLIC_DSN___" }), {
async scheduled(controller, env, ctx) {
await Sentry.withMonitor(
"my-cron-job",
async () => {
// Execute your scheduled task here.
},
{
schedule: { type: "crontab", value: controller.cron },
timezone: "UTC",
}
);
},
});
```

A simple example is if you have a job that runs every minute (1), but takes five (5) minutes to complete each execution.
Use a distinct monitor slug for each schedule. For jobs whose start and completion are tracked separately, use `captureCheckIn` instead.

If this happens, you have to provide a stable check-in ID for your execution with each request to prevent unintended consequences.
</PlatformSection>

Usage example:
<PlatformSection notSupported={["javascript.deno", "javascript.cloudflare"]}>

```bash {tabTitle: cURL}
CHECK_IN_ID="$(uuidgen)"
## Automatic Crons Instrumentation

SENTRY_INGEST="https://___ORG_INGEST_DOMAIN___"
SENTRY_CRONS="${SENTRY_INGEST}/api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/"
The `Sentry.cron` wrappers instrument the `cron`, `node-cron`, and `node-schedule` libraries on Node.js and Bun. They aren't available in browser, Deno, Cloudflare Workers, or Edge SDK entry points. For frameworks that support multiple runtimes, use these wrappers only in the Node.js or Bun server runtime.

# 🟡 Notify Sentry your job is running with a check-in ID:
curl "${SENTRY_CRONS}?check_in_id=${CHECK_IN_ID}&status=in_progress"
<PlatformSection supported={["javascript.bun", "javascript.elysia"]}>

# Execute your scheduled task here...
The Bun SDK re-exports these wrappers from `@sentry/node`. There is no native `Bun.cron` instrumentation. For other schedulers, use `withMonitor` or `captureCheckIn`.

# 🟢 Notify Sentry your job has completed successfully with a check-in ID:
curl "${SENTRY_CRONS}?check_in_id=${CHECK_IN_ID}&status=ok"
```
</PlatformSection>

## Heartbeat
<Include name="javascript-crons-automatic-crons-instrumentation.mdx" />

Heartbeat monitoring notifies Sentry of a job's status through one check-in. This setup will only notify you if your job didn't start when expected (missed). If you need to track a job to see if it exceeded its maximum runtime (failed), use check-ins instead.
</PlatformSection>

```bash {tabTitle: cURL}
SENTRY_INGEST="https://___ORG_INGEST_DOMAIN___"
SENTRY_CRONS="${SENTRY_INGEST}/api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/"
## Job Monitoring

# 🟢 Notify Sentry your job has completed successfully:
curl "${SENTRY_CRONS}?status=ok"
```
<Include name="javascript-crons-job-monitoring.mdx" />

```http {tabTitle: HTTP}
GET /api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/?status=ok HTTP/1.1
Host: ___ORG_INGEST_DOMAIN___
```
## Check-Ins

If your job execution fails:
<Include name="javascript-crons-checkins.mdx" />

```bash {tabTitle: cURL}
# 🔴 Notify Sentry your job has failed:
curl "${SENTRY_CRONS}?status=error"
```
## Upserting Cron Monitors

```http {tabTitle: HTTP}
GET /api/___PROJECT_ID___/cron/<monitor_slug>/___PUBLIC_KEY___/?status=error HTTP/1.1
Host: ___ORG_INGEST_DOMAIN___
```
<Include name="javascript-crons-upsert.mdx" />

</PlatformSection>
</PlatformCategorySection>

## Alerts

Expand Down
15 changes: 10 additions & 5 deletions includes/javascript-crons-automatic-crons-instrumentation.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
If you're using the [`cron`](https://www.npmjs.com/package/cron), [`node-cron`](https://www.npmjs.com/package/node-cron) or [`node-schedule`](https://www.npmjs.com/package/node-schedule) libraries to run your periodic tasks, you can use our instrumentation functions in the `Sentry.cron` export to monitor your cron jobs.
Wrap your scheduler before registering jobs. The wrappers send check-ins for each execution and create or update monitors using the job's schedule. They aren't enabled by `Sentry.init()` alone.

### Cron

Expand All @@ -11,25 +11,30 @@ import { CronJob } from "cron";

const CronJobWithCheckIn = Sentry.cron.instrumentCron(CronJob, "my-cron-job");

// use the constructor
const job = new CronJobWithCheckIn("* * * * *", () => {
console.log("You will see this message every minute");
});

// or from method
job.start();
```

Alternatively, use `CronJob.from`:

```javascript
const job = CronJobWithCheckIn.from({
cronTime: "* * * * *",
onTick: () => {
console.log("You will see this message every minute");
},
start: true,
});
```

### Node Cron

Requires SDK version `7.92.0` or higher.

Use `Sentry.cron.instrumentNodeCron` to instrument the `cron` export from the [`node-cron`](https://www.npmjs.com/package/node-cron) library. This returns an object with the same API as the original `cron` export, but with the `schedule` method instrumented. You can pass the name of the cron monitor and an optional time zone as part of the third options argument to the function.
Use `Sentry.cron.instrumentNodeCron` to wrap the [`node-cron`](https://www.npmjs.com/package/node-cron) library's `schedule` method. A monitor `name` is required in the third argument to `schedule`; `timezone` is optional. Other methods, such as `createTask`, aren't instrumented.

```JavaScript
import cron from "node-cron";
Expand All @@ -49,7 +54,7 @@ cronWithCheckIn.schedule(

Requires SDK version `7.93.0` or higher.

Use `Sentry.cron.instrumentNodeSchedule` to instrument the `schedule` export from the [`node-schedule`](https://www.npmjs.com/package/node-schedule) library. This returns an object with the same API as the original `schedule` export, but with the `scheduleJob` method instrumented. You can pass the name of the cron job as the first argument to the function. Currently this only supports cronstring as the second argument to `scheduleJob`.
Use `Sentry.cron.instrumentNodeSchedule` to wrap the [`node-schedule`](https://www.npmjs.com/package/node-schedule) library's `scheduleJob` method. Pass a job name as the first argument and a crontab string as the second. Date and recurrence-rule schedules aren't supported by this wrapper; use `withMonitor` or `captureCheckIn` instead.

```JavaScript
import * as schedule from "node-schedule";
Expand Down
Loading
Loading