[HDX-5077] Alert-task coverage for multi-series metric tiles - #2907
Conversation
The composed multi-series metric query (#2859) changed how gaps and ratio division-by-zero reach the alert task: a series with no row at a bucket now pivots to an explicit NULL instead of an absent key, and a zero denominator divides to NULL instead of a node-side NaN. Pin the new semantics with the first multi-series metric tile coverage in the checkAlerts int suite: - threshold compares against the LAST select item's value (not an earlier series' value) - a gap in the last series is skipped by the null guard rather than silently backfilled from an earlier series (the old node-side merge fell back to it) - a ratio with a zero denominator is skipped without pushing a NaN count into alert history Also retire the stale 'check if this is still needed' TODO on the null guard: the NULL is now intentional composed-query semantics.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
🔵 Tier 2 — Low RiskSmall, isolated change with no API route or data model modifications. Why this tier:
Additional context: touches background tasks or the delivery pipeline lightly (5 lines, under the 30-line bar for Tier 4) Review process: AI review + quick human skim (target: 5–15 min). Reviewer validates AI assessment and checks for domain-specific concerns. Stats
|
Greptile SummaryThis PR adds integration coverage for multi-series metric-tile alert evaluation while documenting the existing intentional NULL-handling contract.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| packages/api/src/tasks/checkAlerts/tests/checkAlerts.int.test.ts | Adds isolated integration tests covering last-series selection, missing-series gaps, and zero-denominator ratios. |
| packages/api/src/tasks/checkAlerts/index.ts | Updates only the explanatory comment around the unchanged null-value guard. |
Reviews (3): Last reviewed commit: "Merge branch 'main' into warren/hdx-5077..." | Re-trigger Greptile
E2E Test Results✅ All tests passed • 293 passed • 1 skipped • 1150s
Tests ran across 4 shards in parallel. |
Deep ReviewScope: Intent: Add the first multi-series metric-tile coverage to the alert suite and document the null-guard's contract. The three tests trace cleanly against ✅ No critical issues found. 🟡 P2 -- recommended
🔵 P3 nitpicks (4)
Reviewers (4): correctness, testing, maintainability, kieran-typescript. Testing gaps:
|
Why
Follow-up to #2859 (composed multi-series metric query). That PR verified the existing 268 checkAlerts int tests pass unchanged, but the alert suite had zero multi-series metric tile coverage, and the refactor intentionally changed two null/NaN edge cases in how alert evaluation sees multi-series results. This PR pins those semantics with tests written against the shipped implementation.
Behavior deltas pinned (introduced by #2859, both fixes over the old node-side merge)
mergeResultSetsproduced a row with the missing series' key simply absent, soparseAlertData's "last value column wins" silently fell back to an earlier series' value — an arbitrary evaluation. The composed query pivots the gap to an explicitNULL, which the null guard inprocessAlertskips.computeRatioproduced a JSNaNthat slipped past the null guard (NaN != null) and pushed aNaNcount into alert history. The composed query divides to SQLNULL, which the guard skips — exactly what its own comment said it was for.What
checkAlerts.int.test.ts):TILE alert (metrics, multi-series) - threshold compares the last series value— fires on the last select item's value (6), not the first series' (100), and resolves next windowTILE alert (metrics, multi-series) - a gap in the last series is skipped, not backfilled from an earlier series— no ALERT from the first series' above-threshold value; single default OK history with no evaluated valuesTILE alert (metrics, ratio) - a zero denominator yields NULL and is skipped without NaN history— no NaN ever lands inlastValuesTODO: we might want to fix the null value from the upstream (check if this is still needed)on the null guard — the NULL is now intentional composed-query semantics (gap / div-by-zero), documented as the contract. No logic change.Test plan
make dev-int FILE=checkAlerts.int— 164/164 pass (incl. the 3 new tests) against docker CHnpx nx run @hyperdx/api:ci:lintgreen (at the 311-warning ratchet; new tests add zero warnings)tsc --noEmitcleanNo changeset: tests + comment only.
Issues
Linear: HDX-5077