Skip to content

Commit 68bc4dd

Browse files
wedamijaclaude
andauthored
fix(arq): Don't monitor cron jobs with unsupported schedules (#8098)
Part of a series adding automatic Crons monitoring for the most-used job schedulers in each SDK. Check-ins for a monitor that doesn't exist yet are dropped, so today each monitor has to be created by hand with its schedule copied from the code. Sending the job's schedule as the monitor config lets Sentry create the monitor and keep it in sync. This is a quick fix to keep the arq integration behaviour in line with how other integrations work. Sorry for the churn! Follow-up to #8051. Cron jobs whose schedule Crons can't express are no longer monitored, instead of checking in without a config. This matches Celery beat, and the Huey and RQ integrations from #8052 and #8053. Docs: getsentry/sentry-docs#20056 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1c249d8 commit 68bc4dd

2 files changed

Lines changed: 31 additions & 14 deletions

File tree

‎sentry_sdk/integrations/arq.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,11 @@ def _monitor_cron_job(
336336
monitor_config = _get_monitor_config(cron_job, worker)
337337
if monitor_config is None:
338338
logger.debug(
339-
"arq cron job %r can't be expressed as a Sentry Crons schedule. "
340-
"Sending check-ins without a monitor config.",
339+
"Not monitoring arq cron job %r: its schedule can't be expressed "
340+
"as a Sentry Crons schedule.",
341341
cron_job.name,
342342
)
343+
return
343344

344345
coroutine = cron_job.coroutine
345346

‎tests/integrations/arq/test_arq_crons.py‎

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ def info(self, section):
3030
FakeSocket.info = info
3131

3232

33+
@pytest.fixture(autouse=True)
34+
def utc_local_time(monkeypatch):
35+
# arq < 0.25 runs cron jobs in local time.
36+
monkeypatch.setattr(time, "timezone", 0)
37+
monkeypatch.setattr(time, "daylight", 0)
38+
39+
3340
def _check_ins(envelopes):
3441
return [
3542
item.payload.json
@@ -65,10 +72,7 @@ class WorkerSettings:
6572

6673

6774
@pytest.mark.asyncio
68-
async def test_cron_job_ok(sentry_init, capture_envelopes, monkeypatch):
69-
# arq < 0.25 runs cron jobs in local time.
70-
monkeypatch.setattr(time, "timezone", 0)
71-
monkeypatch.setattr(time, "daylight", 0)
75+
async def test_cron_job_ok(sentry_init, capture_envelopes):
7276
sentry_init(integrations=[ArqIntegration(monitor_cron_jobs=True)])
7377
envelopes = capture_envelopes()
7478

@@ -109,20 +113,32 @@ async def test_cron_job_error(sentry_init, capture_envelopes):
109113

110114

111115
@pytest.mark.asyncio
112-
async def test_cron_job_without_config(sentry_init, capture_envelopes):
116+
@pytest.mark.parametrize(
117+
"kwargs, tz",
118+
[
119+
# Every 10 seconds can't be expressed as a crontab.
120+
({"second": {0, 10, 20, 30, 40, 50}}, timezone.utc),
121+
({"day": 1, "weekday": "mon"}, timezone.utc),
122+
({"minute": 0}, timezone(timedelta(hours=5, minutes=30))),
123+
],
124+
)
125+
async def test_unsupported_schedule_not_monitored(
126+
sentry_init, capture_envelopes, monkeypatch, kwargs, tz
127+
):
128+
monkeypatch.setattr(time, "timezone", -tz.utcoffset(None).total_seconds())
113129
sentry_init(integrations=[ArqIntegration(monitor_cron_jobs=True)])
114130
envelopes = capture_envelopes()
131+
calls = []
132+
133+
async def job(ctx):
134+
calls.append(1)
115135

116-
# Every 10 seconds can't be expressed as a crontab.
117136
await _run_cron_jobs(
118-
cron(ok_job, second={0, 10, 20, 30, 40, 50}, run_at_startup=True),
119-
timezone=timezone.utc,
137+
cron(job, name="job", run_at_startup=True, **kwargs), timezone=tz
120138
)
121139

122-
# A scheduled run can follow the startup run.
123-
check_ins = _check_ins(envelopes)
124-
assert [c["status"] for c in check_ins[:2]] == ["in_progress", "ok"]
125-
assert all("monitor_config" not in c for c in check_ins)
140+
assert calls
141+
assert _check_ins(envelopes) == []
126142

127143

128144
@pytest.mark.asyncio

0 commit comments

Comments
 (0)