From be2e72b6bd208ca0a80e28f57e56ec8418b62b08 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Fri, 2 Oct 2026 12:46:24 -0700 Subject: [PATCH 01/15] 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 02/15] 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 03/15] 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 04/15] 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 05/15] 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 06/15] 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. From 69894710be6a17e19c119422c0bd231f9bd7b587 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Mon, 5 Oct 2026 12:24:11 -0700 Subject: [PATCH 07/15] docs(crons): List every Cloudflare schedule sent without a config Co-Authored-By: Claude --- platform-includes/crons/setup/javascript.cloudflare.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 775fe097245c76..d9a9a8fceaa842 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -2,7 +2,7 @@ -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. +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. The in-progress check-in of each run 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, 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: @@ -31,7 +31,7 @@ When you change a schedule in `wrangler.toml`, change its key in `jobs`. The mon 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`. 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. +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 day-of-week field can't be converted, the day-of-month field has `W` or `?`, or both day fields are set, check-ins are sent without a schedule or other monitor options, 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 fd84d049962e4c799fe1eea91bb7c8552f88e549 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Mon, 5 Oct 2026 13:37:45 -0700 Subject: [PATCH 08/15] style(cloudflare): Apply prettier to cron monitor snippet Co-Authored-By: Claude --- platform-includes/crons/setup/javascript.cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index d9a9a8fceaa842..0cedd95104bc89 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -23,7 +23,7 @@ export default Sentry.withSentry( async scheduled(controller, env, ctx) { await jobs[controller.cron]?.run(env); }, - }, + } ); ``` From a345e70a2fc0c9ff149c05b6755cb1416c71dbf3 Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Wed, 7 Oct 2026 18:01:53 +0200 Subject: [PATCH 09/15] docs(cloudflare): Rename the Cron Trigger slug option to monitorSlug --- platform-includes/crons/setup/javascript.cloudflare.mdx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 0cedd95104bc89..dfa85512197194 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -16,7 +16,9 @@ export default Sentry.withSentry( (env) => ({ dsn: env.SENTRY_DSN, integrations: [ - Sentry.cronTriggersIntegration({ slug: (cron) => jobs[cron]?.slug }), + Sentry.cronTriggersIntegration({ + monitorSlug: (cron) => jobs[cron]?.slug, + }), ], }), { @@ -27,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 }`. +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 `monitorSlug` function can also return an object with the slug and other monitor options, such as `{ monitorSlug: "daily-report", maxRuntime: 30 }`. -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. +Without a `monitorSlug` 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`. For Monday to Friday, use `2-6` or `MON-FRI`. If the day-of-week field can't be converted, the day-of-month field has `W` or `?`, or both day fields are set, check-ins are sent without a schedule or other monitor options, and you need to create the monitor in Sentry first. From 99a05a13d9b039bd63f42282ee6e892042b185d2 Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Wed, 7 Oct 2026 18:01:59 +0200 Subject: [PATCH 10/15] docs(cloudflare): Send the schedule when both Cron Trigger day fields are set --- platform-includes/crons/setup/javascript.cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index dfa85512197194..4c56d3f73fecb7 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -33,7 +33,7 @@ When you change a schedule in `wrangler.toml`, change its key in `jobs`. The mon Without a `monitorSlug` 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`. For Monday to Friday, use `2-6` or `MON-FRI`. If the day-of-week field can't be converted, the day-of-month field has `W` or `?`, or both day fields are set, check-ins are sent without a schedule or other monitor options, 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 day-of-week field can't be converted, the day-of-month field has `W` or `?`, or both day fields are set and one of them starts with `*` (such as `*/2`), check-ins are sent without a schedule or other monitor options, 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 753466ba0861a54e6ca27c928e097ede9275311c Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Wed, 7 Oct 2026 18:02:34 +0200 Subject: [PATCH 11/15] docs(cloudflare): Use the Vite plugin and a slug map in the Cron Trigger example --- .../crons/setup/javascript.cloudflare.mdx | 59 ++++++++++++------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 4c56d3f73fecb7..11ac00d82024b5 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -4,32 +4,49 @@ 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. The in-progress check-in of each run 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, 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: +With the Sentry Cloudflare Vite plugin, add the integration to your `instrument.server.*` file. Cron Triggers have no names, and the `scheduled` handler only receives the cron expression. Keep a map from each expression in your wrangler config to its monitor slug in its own module, and use it in `instrument.server.ts` for the slugs and in the `scheduled` handler to select the job: -```javascript -const jobs = { - "30 9 * * MON-FRI": { slug: "daily-report", run: dailyReport }, - "0 */6 * * *": { slug: "sync-inventory", run: syncInventory }, +```typescript {filename:monitorSlugs.ts} +export const monitorSlugs: Record = { + "30 9 * * MON-FRI": "daily-report", + "0 */6 * * *": "sync-inventory", }; +``` + +```typescript {filename:instrument.server.ts} +import * as Sentry from "@sentry/cloudflare"; +import { monitorSlugs } from "./monitorSlugs"; -export default Sentry.withSentry( - (env) => ({ - dsn: env.SENTRY_DSN, - integrations: [ - Sentry.cronTriggersIntegration({ - monitorSlug: (cron) => jobs[cron]?.slug, - }), - ], - }), - { - async scheduled(controller, env, ctx) { - await jobs[controller.cron]?.run(env); - }, - } -); +export default Sentry.defineCloudflareOptions((env) => ({ + dsn: env.SENTRY_DSN, + integrations: [ + Sentry.cronTriggersIntegration({ + monitorSlug: (cron) => monitorSlugs[cron], + }), + ], +})); ``` -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 `monitorSlug` function can also return an object with the slug and other monitor options, such as `{ monitorSlug: "daily-report", maxRuntime: 30 }`. +```typescript {filename:index.ts} +import { monitorSlugs } from "./monitorSlugs"; + +export default { + async scheduled(controller, env, ctx) { + switch (monitorSlugs[controller.cron]) { + case "daily-report": + // Your daily report job + break; + case "sync-inventory": + // Your inventory sync job + break; + } + }, +}; +``` + +If you deploy with `wrangler` directly, pass the same integration to `Sentry.withSentry` in your Worker, as shown in the Wrangler setup. + +When you change a schedule in your wrangler config, change its key in `monitorSlugs`. The monitor keeps its slug, and Sentry updates its schedule on the next check-in. Triggers without an entry send no check-ins. The `monitorSlug` function can also return an object with the slug and other monitor options, such as `{ monitorSlug: "daily-report", maxRuntime: 30 }`. Without a `monitorSlug` 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. From 3293781d101768fba00db27f33d53f1a95cb023e Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Wed, 7 Oct 2026 18:02:45 +0200 Subject: [PATCH 12/15] docs(cloudflare): Explain when to set Cron Trigger monitor slugs --- platform-includes/crons/setup/javascript.cloudflare.mdx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 11ac00d82024b5..1987dfd2ce0e44 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -48,7 +48,10 @@ If you deploy with `wrangler` directly, pass the same integration to `Sentry.wit When you change a schedule in your wrangler config, change its key in `monitorSlugs`. The monitor keeps its slug, and Sentry updates its schedule on the next check-in. Triggers without an entry send no check-ins. The `monitorSlug` function can also return an object with the slug and other monitor options, such as `{ monitorSlug: "daily-report", maxRuntime: 30 }`. -Without a `monitorSlug` 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. +Without a `monitorSlug` function, the slug comes from the cron expression: `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. Set a `monitorSlug` function in these cases: + +- You change a schedule. A new expression gives a new slug, so Sentry creates a new monitor. The old monitor gets no more check-ins and reports missed check-ins, so delete it in Sentry. +- Two or more Workers report to the same project and environment with the same cron expression. Without a `monitorSlug` function, these Workers share one monitor, and the check-ins of one Worker can hide the missed runs of another. 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 day-of-week field can't be converted, the day-of-month field has `W` or `?`, or both day fields are set and one of them starts with `*` (such as `*/2`), check-ins are sent without a schedule or other monitor options, and you need to create the monitor in Sentry first. From 06e2d862e259db6d217e75e0958491dd12e2f73b Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Wed, 7 Oct 2026 18:09:13 +0200 Subject: [PATCH 13/15] docs(cloudflare): List an L-n day of month as sent without a schedule --- platform-includes/crons/setup/javascript.cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 1987dfd2ce0e44..412b2c97d2c9cb 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -53,7 +53,7 @@ Without a `monitorSlug` function, the slug comes from the cron expression: `30 9 - You change a schedule. A new expression gives a new slug, so Sentry creates a new monitor. The old monitor gets no more check-ins and reports missed check-ins, so delete it in Sentry. - Two or more Workers report to the same project and environment with the same cron expression. Without a `monitorSlug` function, these Workers share one monitor, and the check-ins of one Worker can hide the missed runs of another. -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 day-of-week field can't be converted, the day-of-month field has `W` or `?`, or both day fields are set and one of them starts with `*` (such as `*/2`), check-ins are sent without a schedule or other monitor options, 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 day-of-week field can't be converted, the day-of-month field has `W`, `?`, or `L` with an offset (such as `L-3`), or both day fields are set and one of them starts with `*` (such as `*/2`), check-ins are sent without a schedule or other monitor options, 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 e2845602901498a5e1cb4da7729c00d2aa29f48e Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Wed, 7 Oct 2026 18:10:54 +0200 Subject: [PATCH 14/15] docs(cloudflare): Show the three Cron Trigger files one under the other --- platform-includes/crons/setup/javascript.cloudflare.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 412b2c97d2c9cb..3c57dc9d6e7406 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -4,7 +4,7 @@ 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. The in-progress check-in of each run 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. -With the Sentry Cloudflare Vite plugin, add the integration to your `instrument.server.*` file. Cron Triggers have no names, and the `scheduled` handler only receives the cron expression. Keep a map from each expression in your wrangler config to its monitor slug in its own module, and use it in `instrument.server.ts` for the slugs and in the `scheduled` handler to select the job: +With the Sentry Cloudflare Vite plugin, add the integration to your `instrument.server.*` file. Cron Triggers have no names, and the `scheduled` handler only receives the cron expression, so the setup uses three files. First, keep a map from each expression in your wrangler config to its monitor slug in its own module: ```typescript {filename:monitorSlugs.ts} export const monitorSlugs: Record = { @@ -13,6 +13,8 @@ export const monitorSlugs: Record = { }; ``` +Then use the map in `instrument.server.ts` for the slugs: + ```typescript {filename:instrument.server.ts} import * as Sentry from "@sentry/cloudflare"; import { monitorSlugs } from "./monitorSlugs"; @@ -27,6 +29,8 @@ export default Sentry.defineCloudflareOptions((env) => ({ })); ``` +And in the `scheduled` handler of your Worker to select the job: + ```typescript {filename:index.ts} import { monitorSlugs } from "./monitorSlugs"; From 4f19ca29f9d1d2086f4e2311b9619786bc6e3e71 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Tue, 13 Oct 2026 12:05:51 -0700 Subject: [PATCH 15/15] docs(cloudflare): Set the Cron Triggers version to 11.7.0 --- platform-includes/crons/setup/javascript.cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-includes/crons/setup/javascript.cloudflare.mdx b/platform-includes/crons/setup/javascript.cloudflare.mdx index 3c57dc9d6e7406..f5c681793850d7 100644 --- a/platform-includes/crons/setup/javascript.cloudflare.mdx +++ b/platform-includes/crons/setup/javascript.cloudflare.mdx @@ -1,6 +1,6 @@ ## Cron Triggers - + 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. The in-progress check-in of each run 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.