From be2e72b6bd208ca0a80e28f57e56ec8418b62b08 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Fri, 2 Oct 2026 12:46:24 -0700 Subject: [PATCH 1/6] docs(cloudflare): Document opt-in Cron Trigger monitoring Co-Authored-By: Claude Opus 5.5 --- .../crons/setup/javascript.cloudflare.mdx | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index c51440a988a45c..4b2560bdf0ba52 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -1,3 +1,29 @@ +## Cron Triggers + + + +If your Worker runs on [Cron Triggers](https://developers.cloudflare.com/workers/configuration/cron-triggers/), set `monitorCronTriggers` to send check-ins for every run of the `scheduled` handler. Each check-in carries the trigger's cron expression as the schedule, so Sentry creates the monitor on the first run. This option is off by default because each monitor it creates is billed. + +```javascript +export default Sentry.withSentry( + (env) => ({ + dsn: env.SENTRY_DSN, + monitorCronTriggers: true, + }), + { + async scheduled(controller, env, ctx) { + // Your cron job logic here + }, + }, +); +``` + +With `true`, the monitor slug comes from the cron expression: `cron-` followed by the expression with `*` written as `x` and other characters as `-`. For example, `30 9 * * 1-5` becomes `cron-30-9-x-x-1-5`. Workers that report to the same project and share a cron expression share a monitor. To choose the slug yourself, pass a function that receives the cron expression. Return `undefined` to skip a trigger: + +```javascript +monitorCronTriggers: (cron) => (cron === "0 0 * * *" ? "nightly-cleanup" : undefined), +``` + ## Job Monitoring From d52398473258393d6d3c08d7359b6026f48bb31a Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Fri, 2 Oct 2026 13:28:26 -0700 Subject: [PATCH 2/6] docs(cloudflare): Document weekday conversion, slug rules and monitor settings Co-Authored-By: Claude Opus 5.5 --- .../crons/setup/javascript.cloudflare.mdx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 4b2560bdf0ba52..619a6186a13e90 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -18,12 +18,19 @@ export default Sentry.withSentry( ); ``` -With `true`, the monitor slug comes from the cron expression: `cron-` followed by the expression with `*` written as `x` and other characters as `-`. For example, `30 9 * * 1-5` becomes `cron-30-9-x-x-1-5`. Workers that report to the same project and share a cron expression share a monitor. To choose the slug yourself, pass a function that receives the cron expression. Return `undefined` to skip a trigger: +Cloudflare numbers the days of the week from 1 (Sunday) to 7 (Saturday), and Sentry numbers them from 0 (Sunday). The SDK converts the day-of-week field to day names before sending it, so `1-5` is sent as `SUN-THU`. If the field can't be converted, check-ins are sent without a schedule, and you need to create the monitor in Sentry first. + +With `true`, the monitor slug comes from the cron expression: `cron-` followed by the lowercased expression, with spaces written as `-`, `*` as `x`, `,` as `_`, `-` as `to`, and `/` as `by`. For example, `30 9 * * 1-5` becomes `cron-30-9-x-x-1to5`. If the expression has other characters or the slug would be longer than 50 characters, the slug is shortened and ends in a hash of the expression. Workers that report to the same project and share a cron expression share a monitor. + +To choose the slug yourself, pass a function that receives the cron expression. It can return the slug, or an object with the slug and other monitor options. Return `undefined` to skip a trigger: ```javascript -monitorCronTriggers: (cron) => (cron === "0 0 * * *" ? "nightly-cleanup" : undefined), +monitorCronTriggers: (cron) => + cron === "0 0 * * *" ? { slug: "nightly-cleanup", maxRuntime: 30 } : undefined, ``` +Runs without a cron expression, such as some manual runs with `--test-scheduled`, send no check-ins. + ## Job Monitoring From 1d05c77684f93c1194173bcf322f4105782817a8 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Fri, 2 Oct 2026 15:54:12 -0700 Subject: [PATCH 3/6] docs(cloudflare): Use cronTriggersIntegration for Cron Trigger check-ins Co-Authored-By: Claude --- .../crons/setup/javascript.cloudflare.mdx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 619a6186a13e90..b485abf5d649fc 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -2,13 +2,13 @@ -If your Worker runs on [Cron Triggers](https://developers.cloudflare.com/workers/configuration/cron-triggers/), set `monitorCronTriggers` to send check-ins for every run of the `scheduled` handler. Each check-in carries the trigger's cron expression as the schedule, so Sentry creates the monitor on the first run. This option is off by default because each monitor it creates is billed. +If your Worker runs on [Cron Triggers](https://developers.cloudflare.com/workers/configuration/cron-triggers/), add `cronTriggersIntegration` to send check-ins for every run of the `scheduled` handler. Each check-in carries the trigger's cron expression as the schedule, so Sentry creates the monitor on the first run. The integration isn't enabled by default because each monitor it creates is billed. ```javascript export default Sentry.withSentry( (env) => ({ dsn: env.SENTRY_DSN, - monitorCronTriggers: true, + integrations: [Sentry.cronTriggersIntegration()], }), { async scheduled(controller, env, ctx) { @@ -20,13 +20,17 @@ export default Sentry.withSentry( Cloudflare numbers the days of the week from 1 (Sunday) to 7 (Saturday), and Sentry numbers them from 0 (Sunday). The SDK converts the day-of-week field to day names before sending it, so `1-5` is sent as `SUN-THU`. If the field can't be converted, check-ins are sent without a schedule, and you need to create the monitor in Sentry first. -With `true`, the monitor slug comes from the cron expression: `cron-` followed by the lowercased expression, with spaces written as `-`, `*` as `x`, `,` as `_`, `-` as `to`, and `/` as `by`. For example, `30 9 * * 1-5` becomes `cron-30-9-x-x-1to5`. If the expression has other characters or the slug would be longer than 50 characters, the slug is shortened and ends in a hash of the expression. Workers that report to the same project and share a cron expression share a monitor. +By default, the monitor slug comes from the cron expression: `cron-` followed by the lowercased expression, with spaces written as `-`, `*` as `x`, `,` as `_`, `-` as `to`, and `/` as `by`. For example, `30 9 * * 1-5` becomes `cron-30-9-x-x-1to5`. If the expression has other characters or the slug would be longer than 50 characters, the slug is shortened and ends in a hash of the expression. Workers that report to the same project and share a cron expression share a monitor. -To choose the slug yourself, pass a function that receives the cron expression. It can return the slug, or an object with the slug and other monitor options. Return `undefined` to skip a trigger: +To choose the slug yourself, pass a `slug` function that receives the cron expression. It can return the slug, or an object with the slug and other monitor options. Return `undefined` to skip a trigger: ```javascript -monitorCronTriggers: (cron) => - cron === "0 0 * * *" ? { slug: "nightly-cleanup", maxRuntime: 30 } : undefined, +integrations: [ + Sentry.cronTriggersIntegration({ + slug: (cron) => + cron === "0 0 * * *" ? { slug: "nightly-cleanup", maxRuntime: 30 } : undefined, + }), +], ``` Runs without a cron expression, such as some manual runs with `--test-scheduled`, send no check-ins. From ffd90239203f3187a4a72ae5b7b0baffea4f9059 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Fri, 2 Oct 2026 16:02:02 -0700 Subject: [PATCH 4/6] docs(cloudflare): Lead with named Cron Trigger slugs Co-Authored-By: Claude --- .../crons/setup/javascript.cloudflare.mdx | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index b485abf5d649fc..d41d79fbb8612c 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -4,11 +4,21 @@ If your Worker runs on [Cron Triggers](https://developers.cloudflare.com/workers/configuration/cron-triggers/), add `cronTriggersIntegration` to send check-ins for every run of the `scheduled` handler. Each check-in carries the trigger's cron expression as the schedule, so Sentry creates the monitor on the first run. The integration isn't enabled by default because each monitor it creates is billed. +Cron Triggers have no names, so give each one a monitor slug, keyed by the cron expression from your `wrangler.toml`: + ```javascript export default Sentry.withSentry( (env) => ({ dsn: env.SENTRY_DSN, - integrations: [Sentry.cronTriggersIntegration()], + integrations: [ + Sentry.cronTriggersIntegration({ + slug: (cron) => + ({ + "30 9 * * 1-5": "daily-report", + "0 */6 * * *": "sync-inventory", + })[cron], + }), + ], }), { async scheduled(controller, env, ctx) { @@ -18,20 +28,11 @@ export default Sentry.withSentry( ); ``` -Cloudflare numbers the days of the week from 1 (Sunday) to 7 (Saturday), and Sentry numbers them from 0 (Sunday). The SDK converts the day-of-week field to day names before sending it, so `1-5` is sent as `SUN-THU`. If the field can't be converted, check-ins are sent without a schedule, and you need to create the monitor in Sentry first. - -By default, the monitor slug comes from the cron expression: `cron-` followed by the lowercased expression, with spaces written as `-`, `*` as `x`, `,` as `_`, `-` as `to`, and `/` as `by`. For example, `30 9 * * 1-5` becomes `cron-30-9-x-x-1to5`. If the expression has other characters or the slug would be longer than 50 characters, the slug is shortened and ends in a hash of the expression. Workers that report to the same project and share a cron expression share a monitor. +When you change a trigger's schedule, update its entry so the monitor keeps its slug. Sentry then updates the monitor's schedule on the next check-in. Triggers the function returns `undefined` for send no check-ins. The function can also return an object with the slug and other monitor options, such as `{ slug: "daily-report", maxRuntime: 30 }`. -To choose the slug yourself, pass a `slug` function that receives the cron expression. It can return the slug, or an object with the slug and other monitor options. Return `undefined` to skip a trigger: +Without a `slug` function, the slug comes from the cron expression, so it changes when the schedule changes: `30 9 * * 1-5` becomes `cron-30-9-x-x-1to5` (`*` is written as `x`, `,` as `_`, `-` as `to`, and `/` as `by`). Expressions with other characters, or slugs longer than 50 characters, end in a hash of the expression. Workers that report to the same project and share a cron expression share a monitor. -```javascript -integrations: [ - Sentry.cronTriggersIntegration({ - slug: (cron) => - cron === "0 0 * * *" ? { slug: "nightly-cleanup", maxRuntime: 30 } : undefined, - }), -], -``` +Cloudflare numbers the days of the week from 1 (Sunday) to 7 (Saturday), and Sentry numbers them from 0 (Sunday). The SDK converts the day-of-week field to day names before sending it, so `1-5` is sent as `SUN-THU`. If the field can't be converted, check-ins are sent without a schedule, and you need to create the monitor in Sentry first. Runs without a cron expression, such as some manual runs with `--test-scheduled`, send no check-ins. From c08c3afe8ee5b6e75efa170f96717691289695a6 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Fri, 2 Oct 2026 16:04:31 -0700 Subject: [PATCH 5/6] docs(cloudflare): Use one jobs map for Cron Trigger dispatch and slugs Co-Authored-By: Claude --- .../crons/setup/javascript.cloudflare.mdx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index d41d79fbb8612c..323e9246b35a97 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -4,31 +4,30 @@ If your Worker runs on [Cron Triggers](https://developers.cloudflare.com/workers/configuration/cron-triggers/), add `cronTriggersIntegration` to send check-ins for every run of the `scheduled` handler. Each check-in carries the trigger's cron expression as the schedule, so Sentry creates the monitor on the first run. The integration isn't enabled by default because each monitor it creates is billed. -Cron Triggers have no names, so give each one a monitor slug, keyed by the cron expression from your `wrangler.toml`: +Cron Triggers have no names, and the `scheduled` handler only receives the cron expression. Keep one entry per trigger, keyed by its expression from `wrangler.toml`, with the job and its monitor slug, and use it for both: ```javascript +const jobs = { + "30 9 * * 1-5": { slug: "daily-report", run: dailyReport }, + "0 */6 * * *": { slug: "sync-inventory", run: syncInventory }, +}; + export default Sentry.withSentry( (env) => ({ dsn: env.SENTRY_DSN, integrations: [ - Sentry.cronTriggersIntegration({ - slug: (cron) => - ({ - "30 9 * * 1-5": "daily-report", - "0 */6 * * *": "sync-inventory", - })[cron], - }), + Sentry.cronTriggersIntegration({ slug: (cron) => jobs[cron]?.slug }), ], }), { async scheduled(controller, env, ctx) { - // Your cron job logic here + await jobs[controller.cron]?.run(env); }, }, ); ``` -When you change a trigger's schedule, update its entry so the monitor keeps its slug. Sentry then updates the monitor's schedule on the next check-in. Triggers the function returns `undefined` for send no check-ins. The function can also return an object with the slug and other monitor options, such as `{ slug: "daily-report", maxRuntime: 30 }`. +When you change a schedule in `wrangler.toml`, change its key in `jobs`. The monitor keeps its slug, and Sentry updates its schedule on the next check-in. Triggers without an entry send no check-ins. The `slug` function can also return an object with the slug and other monitor options, such as `{ slug: "daily-report", maxRuntime: 30 }`. Without a `slug` function, the slug comes from the cron expression, so it changes when the schedule changes: `30 9 * * 1-5` becomes `cron-30-9-x-x-1to5` (`*` is written as `x`, `,` as `_`, `-` as `to`, and `/` as `by`). Expressions with other characters, or slugs longer than 50 characters, end in a hash of the expression. Workers that report to the same project and share a cron expression share a monitor. From ab26c349aeaebcab006d3130237bc7ca564cf3e2 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Fri, 2 Oct 2026 17:41:55 -0700 Subject: [PATCH 6/6] docs(crons): Use MON-FRI in the Cloudflare weekday example On Cloudflare 1 = Sunday, so `1-5` runs Sunday to Thursday. Co-Authored-By: Claude --- platform-includes/crons/setup/javascript.cloudflare.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 323e9246b35a97..775fe097245c76 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -8,7 +8,7 @@ Cron Triggers have no names, and the `scheduled` handler only receives the cron ```javascript const jobs = { - "30 9 * * 1-5": { slug: "daily-report", run: dailyReport }, + "30 9 * * MON-FRI": { slug: "daily-report", run: dailyReport }, "0 */6 * * *": { slug: "sync-inventory", run: syncInventory }, }; @@ -29,9 +29,9 @@ export default Sentry.withSentry( When you change a schedule in `wrangler.toml`, change its key in `jobs`. The monitor keeps its slug, and Sentry updates its schedule on the next check-in. Triggers without an entry send no check-ins. The `slug` function can also return an object with the slug and other monitor options, such as `{ slug: "daily-report", maxRuntime: 30 }`. -Without a `slug` function, the slug comes from the cron expression, so it changes when the schedule changes: `30 9 * * 1-5` becomes `cron-30-9-x-x-1to5` (`*` is written as `x`, `,` as `_`, `-` as `to`, and `/` as `by`). Expressions with other characters, or slugs longer than 50 characters, end in a hash of the expression. Workers that report to the same project and share a cron expression share a monitor. +Without a `slug` function, the slug comes from the cron expression, so it changes when the schedule changes: `30 9 * * MON-FRI` becomes `cron-30-9-x-x-montofri` (`*` is written as `x`, `,` as `_`, `-` as `to`, and `/` as `by`). Expressions with other characters, or slugs longer than 50 characters, end in a hash of the expression. Workers that report to the same project and share a cron expression share a monitor. -Cloudflare numbers the days of the week from 1 (Sunday) to 7 (Saturday), and Sentry numbers them from 0 (Sunday). The SDK converts the day-of-week field to day names before sending it, so `1-5` is sent as `SUN-THU`. If the field can't be converted, check-ins are sent without a schedule, and you need to create the monitor in Sentry first. +Cloudflare numbers the days of the week from 1 (Sunday) to 7 (Saturday), and Sentry numbers them from 0 (Sunday). The SDK converts the day-of-week field to day names before sending it, so `1-5` is sent as `SUN-THU`. For Monday to Friday, use `2-6` or `MON-FRI`. If the field can't be converted, check-ins are sent without a schedule, and you need to create the monitor in Sentry first. Runs without a cron expression, such as some manual runs with `--test-scheduled`, send no check-ins.