You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
postgres data-observability - use cron to precisely schedule queries (DataDog#23529)
* postgres data-observability - use cron to precisely schedule queries
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* review
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* fix: apply ddev formatter
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* Skip invalid queries at construction time
Signed-off-by: Maciej Obuchowski <maciej.obuchowski@datadoghq.com>
* remove lookback as configurable param
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* Replace croniter with datadog_checks_base CronScheduler utility
Drop the third-party croniter==6.2.2 dependency and rewrite the cron
scheduling in PostgresDataObservability on top of the CronExpression /
CronScheduler utilities added to datadog_checks_base in DataDog#23741.
Changes:
- _filter_valid_queries: build a CronScheduler per monitor_id inside a
try/except(ValueError, TypeError) instead of calling croniter.is_valid.
Scheduler captures startup_lookback at construction time.
- _get_due_queries: collapse the entire cron branch to a single
due_ticks(now) call; state registration, lookback recovery, tick
detection, and advancement are all handled by CronScheduler.
- run_job: remove the post-fire croniter re-advance; due_ticks() already
advanced the scheduler at poll time.
- Tests: replace _next_run[mid] accesses with _schedulers[mid].next_tick;
update boundary test to reflect CronScheduler's inclusive (<=) lookback
semantics vs the old strict (<) comparison.
- Remove croniter from agent_requirements.in, postgres/pyproject.toml,
and LICENSE-3rdparty.csv; bump datadog-checks-base pin to >=37.39.0
(first release shipping cron.py).
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* Address code review: type hints, explicit state returns, lateness comment, error guard
- _filter_valid_queries: add Iterable[Query] parameter type; return
(tuple[Query,...], dict[int,CronScheduler]) so callers own the
assignment — removes the hidden self._schedulers side-effect. __init__
now assigns both fields explicitly.
- _get_due_queries: remove setdefault seed for _last_execution; use
.get() and treat None as first-sight. Scheduling-state mutations
(seed and advance) are now consolidated in run_job.
- run_job: add comment distinguishing lateness (scheduling delay) from
execution time; wrap emit_failures count in a nested try/except so a
concurrent _shutdown() cannot turn the error handler into a job crash.
- Tests: merge _make_cron_lookback_check into _make_cron_check via
optional window_seconds/monkeypatch params; collapse three identical
lookback-window tests into one parametrized test_cron_startup_lookback_window_behavior.
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* fmt
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* code review fixes
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* postgres DO: fix cron boundary miss and improve schedule error message
- due_ticks now probes now+0.001 so a first poll landing exactly on a
cron tick boundary fires instead of skipping the cycle
- invalid cron schedule warning now includes the exception message and
the monitor_id to help customers identify and fix the bad config
- regression test added for the exact-boundary case
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* revert cron.py boundary fix (moved to postgres data_observability)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* fix cron exact-boundary detection without inflating lookback window
The previous +0.001 epsilon was passed directly to due_ticks(), which
caused CronScheduler to compare (now+0.001) - prev <= lookback, breaking
the inclusive-boundary test where now - prev == lookback exactly.
Instead, call due_ticks(now) normally and only on the first poll (before
next_tick is cached) probe previous_tick(before=now+0.001) to detect
whether now itself is a tick. This isolates the epsilon to the boundary
detection and leaves the lookback window comparison untouched.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
* simplify cron boundary fix; update over-precise test
Use due_ticks(now + 0.001) — the simpler approach. The previous complex
wrapper was added to avoid breaking test_cron_startup_lookback_boundary_inclusive,
which was asserting now - prev == window exactly. That exact-equality check
belongs in test_cron.py (CronScheduler unit tests), not here. Updated the
test to use a clock 55s after the tick (clearly inside the 60s window),
keeping the meaningful assertion that recovery fires inside the window and
does not fire outside it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
---------
Signed-off-by: mobuchowski <maciej.obuchowski@datadoghq.com>
Signed-off-by: Maciej Obuchowski <maciej.obuchowski@datadoghq.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
description='How often (in seconds) to run this query. Ignored when schedule is set\n(see schedule for the precedence rule).\n',
178
+
)
176
179
monitor_id: int
177
180
query: str
181
+
schedule: Optional[str] =Field(
182
+
None,
183
+
description='A standard 5-field cron expression (minute hour dom month dow) specifying\nwhen to run this query. When both schedule and interval_seconds are set,\nschedule wins and interval_seconds is ignored. If neither is set, the\nquery is skipped at runtime with a warning.\n',
0 commit comments