This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry.
Project Overview
workers-monitor is a Cloudflare Worker that watches a small fleet of my
own Workers. Hourly cron, pulls fleet metrics from Cloudflare's GraphQL
Analytics API, runs a deterministic threshold gate, and only calls Claude
Haiku to judge signal-vs-noise if the gate trips. If Haiku confirms
something's actually wrong, it sends a Telegram alert. A quiet hour makes
zero LLM calls.
github.com/dannwaneri/workers-monitor
Real alert history from the deployed Worker — the daily heartbeat, and
scrolled back, the genuine incidents this system has actually caught.
This submission covers two bugs, found days apart, that turn out to be
the same failure mode wearing different clothes: code that compiles,
deploys cleanly, and runs without throwing — and still doesn't do the one
thing it was written for. "No error" is not the same claim as "working
correctly," and both bugs below only exist because that distinction got
missed once.
Bug Fix or Performance Improvement
Bug 1: the maintenance window's fail-open gap
workers-monitor has a maintenance-window feature — POST a start/end
time and it suppresses Telegram alerts during a planned deploy, without
stopping the gate or the logging. The function that reads that window had
one non-negotiable rule, written as a comment directly above it:
Malformed data fails OPEN (returns null → no suppression) — a broken
window read must never accidentally silence a real incident.
The code didn't actually satisfy that comment:
async function readMaintenanceWindow(env: Env): Promise<MaintenanceWindow | null> {
const raw = await env.STATE.get(MAINTENANCE_KEY);
if (!raw) return null;
try {
const w = JSON.parse(raw) as MaintenanceWindow;
if (Number.isNaN(Date.parse(w.start)) || Number.isNaN(Date.parse(w.end))) {
throw new Error("unparseable start/end timestamps");
}
return w;
} catch (err) {
console.error(/* ... */);
return null;
}
}
Enter fullscreen mode Exit fullscreen mode
Only JSON.parse and the timestamp validation sit inside the try block
— await env.STATE.get(...) on the line above does not. A genuine KV
read failure (a real outage, not bad data) throws an exception nothing in
this function catches. It propagates out of readMaintenanceWindow, out
of the run() function that calls it, and aborts the entire hourly run —
not just alert suppression, but the deterministic gate, the Haiku
judgement call, and the structured logging for that hour, all of it,
silently skipped. Every KV blip during that window meant a full hour of
zero fleet visibility, not just a missed alert.
I found this via a structured review of the diff against the original
spec's acceptance criteria, not a live incident. One criterion was almost
word-for-word the comment above the function — the review caught that the
code only satisfied half of that sentence.
Between the two bugs: closing the class of gap, not just the instance
Fixing bug 1 raised an obvious follow-up question: what happens when
workers-monitor itself breaks, not the fleet it watches? Nothing —
console.error into wrangler tail, unread unless I happened to be
watching. So I wired in Sentry: Sentry.withSentry() around the handler
for automatic error capture, an explicit Sentry.captureException() on
the deliberately-swallowed exception in the scheduled handler's own
catch, and Sentry.withMonitor() around the hourly run() call so a
dead cron trigger gets caught immediately instead of waiting up to 24
hours for the next Telegram heartbeat to go silent.
I deployed it, watched a cron tick complete without error, and considered
cron monitoring done.
Bug 2: the cron monitor that was never actually monitoring
It wasn't done. While recording a demo video of the Sentry integration —
for a separate piece of this challenge — I opened the Monitors dashboard
to screenshot the cron check-in, and there wasn't one. Only Sentry's own
auto-created generic "Error Monitor," nothing for workers-monitor-hourly-poll
at all, despite the code executing successfully every hour for days.
Sentry.withMonitor("workers-monitor-hourly-poll", () => run(event, env))
Enter fullscreen mode Exit fullscreen mode
This isn't wrong syntax. It compiles, deploys, executes the wrapped
function fine. But the check-in has nowhere to attach without a schedule
— Sentry needs to know what "on time" means for this monitor before it
will create a Cron Monitor entity to check in against. Without that
config, the call silently has no monitor to report to. No error, no
warning, just nothing showing up. Exactly the same shape as bug 1: code
that runs clean and still isn't doing its job.
Code
github.com/dannwaneri/workers-monitor/pull/1 — the fail-open fix, isolated, 12 insertions / 1 deletion.
github.com/dannwaneri/workers-monitor/pull/3 — the cron monitor fix, isolated, 14 insertions / 1 deletion.
// Bug 1 fix — env.STATE.get() gets its own try/catch, separate from the
// existing one around JSON.parse:
async function readMaintenanceWindow(env: Env): Promise<MaintenanceWindow | null> {
let raw: string | null;
try {
raw = await env.STATE.get(MAINTENANCE_KEY);
} catch (err) {
console.error(JSON.stringify({
event: "maintenance_window_read_error",
error: err instanceof Error ? err.message : String(err),
}));
return null;
}
if (!raw) return null;
try {
const w = JSON.parse(raw) as MaintenanceWindow;
if (Number.isNaN(Date.parse(w.start)) || Number.isNaN(Date.parse(w.end))) {
throw new Error("unparseable start/end timestamps");
}
return w;
} catch (err) {
console.error(/* ... */);
return null;
}
}
Enter fullscreen mode Exit fullscreen mode
// Bug 2 fix — the missing monitorConfig, matching the real deployed schedule:
Sentry.withMonitor(
"workers-monitor-hourly-poll",
() => run(event, env),
{
schedule: { type: "crontab", value: "0 * * * *" }, // matches wrangler.jsonc's trigger
checkinMargin: 5, // minutes late before considered missed
maxRuntime: 5, // minutes before considered timed out
timezone: "UTC", // Cloudflare cron triggers always run in UTC
},
)
Enter fullscreen mode Exit fullscreen mode
My Improvements
Neither fix is large. What connects them is how each was actually
verified, not assumed:
For bug 1, I ran a two-part review before trusting the diff: does it
satisfy every Given/When/Then acceptance criterion from the original
spec, and separately, does it resolve every assumption flagged during
design, including ones nobody had explicitly revisited. That second check
is what surfaced it — the acceptance criterion for KV-failure behavior
was already written down before the code existed, and the implementation
simply didn't fully match its own spec.
For bug 2, the same discipline applied to my own claim: I'd told myself
"deployed, ran without error, cron monitoring is working." I checked the
Monitors dashboard before the fix (empty — confirmed the bug was real,
not a hunch), deployed the fix, waited for a genuine production cron
tick — not a local test, not a manual trigger — and only considered it
done once workers-monitor-hourly-poll actually appeared as a registered
Cron monitor with an "Every hour" schedule.
The broader lesson, true of both bugs: "the code deployed and nothing
crashed" is a dramatically weaker claim than "the thing I built does what
I said it does." Those two can look identical from a terminal and be
completely different in reality.
Best Use of Sentry
Both Error Monitoring and Cron Monitoring are used here, and bug 2 is
specifically about making the Cron Monitoring half actually work as
intended, not just installed:
-
Automatic error capture —
Sentry.withSentry()wraps the handler, instrumentingfetchandscheduled. -
Explicit capture on the swallowed exception — the scheduled
handler already had a deliberate top-level
try/catchso one bad run doesn't crash the Worker. That's exactly the casewithSentry's automatic uncaught-exception capture can't see, since the exception is caught before it ever becomes "uncaught" — so the catch block also callsSentry.captureException(err)directly. -
Cron monitoring, now actually registering — after the bug 2 fix,
workers-monitor-hourly-pollshows up as a real Cron monitor with an "Every hour" schedule. If the trigger stops firing entirely, Sentry now catches that immediately, instead of the previous 24-hour blind spot (the daily Telegram heartbeat was the only prior proof-of-life).
Verified, not assumed, on both fronts: for error capture, I deployed
a temporary route that threw an intentional error, confirmed it was
captured in the Sentry dashboard, then removed the route before opening
the PR. For cron monitoring, the Monitors dashboard was checked empty
before the fix and populated after a real hourly tick — not a claim, a
before/after I watched happen.
The resolved issues, the real stack trace, and the moment the cron
monitor actually registered — the same evidence, on screen.
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.