[HDX-4997] Persist alert evaluation errors and analytics in AlertHistory - #2797
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🔴 Tier 4 — CriticalTouches authentication, tenancy data models, the public API or shipped database config — or substantially changes background tasks, the OTel pipeline, image build, or release CI. Why this tier:
Review process: Deep review from a domain expert. Synchronous walkthrough may be required. Stats
|
Greptile SummaryThis PR adds the alert-evaluation write path needed to preserve evaluation failures and diagnostics in AlertHistory.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the wrapped-timeout issue is fixed by traversing the production wrapper’s cause, and the separate pagination-gap thread is resolved by a cursor that advances across empty scan slices.
|
| Filename | Overview |
|---|---|
| packages/api/src/tasks/checkAlerts/errors.ts | Walks bounded, cycle-safe error cause chains to classify wrapped ClickHouse and socket timeouts. |
| packages/api/src/tasks/checkAlerts/index.ts | Attributes failures and evaluation analytics to the scheduled window while excluding ERROR histories from retry and consecutive-window state. |
| packages/api/src/tasks/checkAlerts/providers/default.ts | Upserts one ERROR history per alert window and removes a stale same-window error after a clean retry. |
| packages/api/src/tasks/checkAlerts/providers/index.ts | Extends the provider contract with optional evaluation-window and analytics inputs while retaining compatibility. |
| packages/common-utils/src/clickhouse/index.ts | Exposes the configured request timeout for actionable alert timeout messages. |
| packages/api/src/tasks/checkAlerts/tests/errors.test.ts | Covers direct, wrapped, nested, non-timeout, and cyclic timeout-classification inputs. |
| packages/api/src/tasks/checkAlerts/tests/checkAlerts.int.test.ts | Exercises ERROR persistence, retry cleanup, deduplication, backfill behavior, webhook failures, and analytics. |
Sequence Diagram
sequenceDiagram
participant Task as Alert task
participant CH as ClickHouse
participant Provider as AlertProvider
participant Mongo as AlertHistory
participant Hook as Webhook
Task->>CH: Evaluate alert window
alt Query fails
CH-->>Task: Error / timeout
Task->>Provider: recordAlertErrors(window, analytics)
Provider->>Mongo: Upsert ERROR history
else Query succeeds
CH-->>Task: Query results
Task->>Hook: Deliver notification when required
Hook-->>Task: Success or failure
Task->>Provider: updateAlertState(histories, errors)
Provider->>Mongo: Persist normal histories
alt Notification failed
Provider->>Mongo: Upsert same-window ERROR history
else Clean same-window retry
Provider->>Mongo: Delete stale ERROR history
end
end
Reviews (11): Last reviewed commit: "feat(alerts): persist evaluation errors ..." | Re-trigger Greptile
E2E Test Results✅ All tests passed • 268 passed • 1 skipped • 939s
Tests ran across 4 shards in parallel. |
|
<!-- deep-review --> Deep Review
✅ No critical issues found. 🟡 P2 -- recommended
🔵 P3 nitpicks (5)
Reviewers (6): correctness/orchestrator analysis, adversarial-verifier (pagination), adversarial-verifier (history-strip UI), test-inventory reader, shared-types + frontend reader, ClickHouse client type reader. Testing gaps:
|
|
Pushed three fixes:
The pagination-gap comment is addressed by the |
🦋 Changeset detectedLatest commit: 78111b0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Deep ReviewThe multi-agent review was invoked ( What failedEvery This reproduced on:
The fallback routes were also unavailable:
Why no findings were emitted insteadA review assembled from guessed file paths could not distinguish code introduced by this PR from pre-existing code, and could not verify removed lines at all. Since the wrapper's rubric grades on breakage introduced by this diff, and downstream automation treats Suggested remediation for the workflow
Re-run once Reviewers (0): none dispatched — aborted at Stage 1 scope detection. Testing gaps: not assessed — requires the diff. |
4fac62f to
6542632
Compare
6542632 to
066e7c2
Compare
|
<!-- deep-review --> Deep Review🔴 P0/P1 — must fix
🟡 P2 — recommended
🔵 P3 nitpicks (6)
Reviewers (9): correctness, reliability, adversarial, testing, maintainability, project-standards, api-contract, kieran-typescript, performance. Testing gaps:
Environment note: Suppressed below the confidence bar: a claim that |
066e7c2 to
05befe8
Compare
… (HDX-4997) When an alert evaluation fails (ClickHouse query error/timeout, webhook failure), the only persisted signal was alert.executionErrors — a latest-only snapshot wiped by the next successful run. - Failed evaluations are recorded as ERROR-state AlertHistory rows carrying error type/message/timestamp, upserted per evaluation window so per-tick retries collapse into a single row; rows expire with the existing 30d TTL. - Webhook/notification failures also produce an ERROR row alongside the normal evaluation rows; a stale ERROR row from a failed earlier tick is removed when a clean same-window retry succeeds. - Retry/backfill semantics are untouched: ERROR rows are excluded from the due-ness gate, the retry date-range computation, and consecutive-window counting — recording an error never marks the window as evaluated, so the failed window is still retried every tick and backfilled on recovery. - Query timeouts are classified as QUERY_TIMEOUT (client request timeout/abort, server-side TIMEOUT_EXCEEDED/159, socket timeouts — walking the cause chain since the query client wraps failures) with an actionable message that includes the configured evaluation timeout. - Evaluation analytics (queryDurationMs, webhookDurationMs, backfilledBuckets) are recorded on every history row the evaluation writes, including ERROR rows.
05befe8 to
78111b0
Compare
|
Closing: per the decision to keep a single PR, this branch was fast-forwarded into #2786's branch ( |
Summary
When an alert evaluation fails (ClickHouse query error/timeout, webhook failure), the only persisted signal was
alert.executionErrors— a latest-only snapshot wiped by the next successful run. Users couldn't see when evaluations failed, how often, or why. This is a prerequisite for ever tightening the alert query evaluation timeout (HDX-4977).This PR is the write side: the alert task records what #2786 displays.
ERROR-stateAlertHistoryrows carrying error type/message/timestamp, upserted per evaluation window so per-tick retries collapse into a single row (a permanently failing 1d alert produces 1 row/day, not 1/minute; rows expire with the existing 30d TTL).QUERY_TIMEOUT(client request timeout/abort, server-sideTIMEOUT_EXCEEDED/159, socket timeouts — walking the errorcausechain, sinceBaseClickhouseClient.querywraps failures and keeps the identifying metadata only oncause) with an actionable message that includes the configured evaluation timeout.queryDurationMs— time-to-failure on query-error rows,webhookDurationMs— total delivery wall time incl. retries,backfilledBuckets— missed ticks caught up in this run) are recorded on every history row the evaluation writes.How to test on Vercel preview
N/A — the alerting job doesn't run in LOCAL_MODE previews. Covered by integration tests.
How this was tested
tsc --noEmit;errors.testunit suite (18 tests: classification incl. wrapped/nested/self-referential cause chains)QUERY_TIMEOUTclassification, failed-window-still-retried/backfilled, webhook-failure ERROR rows (incl. grouped alerts), analytics fields (steady state + backfill)References