fix: align alert chart markers with the evaluated bucket start - #2928
fix: align alert chart markers with the evaluated bucket start#2928wrn14897 wants to merge 9 commits into
Conversation
Alert firing/recovery markers were drawn at the evaluation time (createdAt, the bucket end), while charts plot each bucket's value at its start and the evaluation history table shows the newest evaluated bucket start — leaving the marker one bucket to the right of both. getAlertTransitionsInRange now emits bucketStart (the newest lastValues.startTime across the window's rows, falling back to createdAt − interval like the table), and annotations are drawn there.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: d66c936 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 |
🟡 Tier 3 — StandardIntroduces new logic, modifies core functionality, or touches areas with non-trivial risk. Why this tier:
Review process: Full human review — logic, architecture, edge cases. Stats
|
E2E Test Results✅ All tests passed • 296 passed • 1 skipped • 969s
Tests ran across 4 shards in parallel. |
Greptile SummaryThe PR aligns alert transition annotations with the newest evaluated bucket while retaining compatibility with older transition payloads.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| packages/api/src/controllers/alertHistory.ts | Derives transition marker times from evaluated bucket starts, with empty-history fallback and range-start flooring. |
| packages/api/src/controllers/tests/alertHistory.int.test.ts | Adds broad integration coverage and correctly types alert identifiers as Mongoose object IDs. |
| packages/app/src/hooks/useAlertAnnotations.tsx | Maps annotations to bucketStart while preserving createdAt compatibility for older responses. |
| packages/app/src/hooks/tests/useAlertAnnotations.test.tsx | Covers bucket-based marker placement, fallback behavior, and key uniqueness. |
| packages/common-utils/src/types.ts | Extends the shared transition schema with validated timestamps and an optional bucketStart field. |
Sequence Diagram
sequenceDiagram
participant History as AlertHistory
participant API as Transitions endpoint
participant App as Annotation mapping
participant Chart as Time chart
History->>API: Evaluation rows and lastValues.startTime
API->>API: Select newest bucket start
API-->>App: createdAt, state, bucketStart
App->>App: "time = bucketStart ?? createdAt"
App-->>Chart: Firing/recovery annotation
Reviews (7): Last reviewed commit: "style: format newestBucketStart signatur..." | Re-trigger Greptile
Deep Review✅ No critical issues found. No data loss, auth, injection, or happy-path crash is introduced; the 🟡 P2 -- recommended
🔵 P3 nitpicks (5)
Reviewers (10): correctness, testing, maintainability, project-standards, api-contract, performance, kieran-typescript, adversarial, agent-native, learnings-researcher. Testing gaps:
|
Addresses review feedback: the test helpers declared alertId as any, dropping compile-time validation on values reaching AlertHistory.create.
…:hyperdxio/hyperdx into warren/fix-markers-in-alert-details-page
Replaces the nested $max array-expression accumulator with the file's established DocumentDB-safe pattern: $push whole lastValues arrays and derive the newest bucket start in JS (see mapGroupedHistories). Also adds a multi-transition annotation test asserting each marker lands on its own transition's bucketStart.
|
Re: Deep Review findings —
Addressed in 35e44a1: dropped the nested
Declined: the two sites operate on different shapes in different contexts — the controller derives from grouped aggregation rows (
Addressed in 35e44a1: added |
…ess (#2928) Deep Review follow-ups: assert an OK transition derives bucketStart from its recovering window's lastValues, document that an edge crossing may emit bucketStart before the range start (charts clamp), tighten the transition schema to ISO datetimes, and assert annotation keys stay distinct for opposite-state transitions sharing a time.
|
Re: Deep Review round 2 — all four items addressed in 782ba43 (note: that round's prose reviewed the pre-35e44a11b head; the nested
Clamping was already verified:
Added
Done for both fields — the only producer emits
Added |
|
Re: Deep Review round 3 —
Declined, deliberately: (Also pushed badaee5 fixing the |
Deep Review follow-ups: an edge crossing's derived bucketStart could precede the range start and render at or left of a carry-in pin, inverting the firing/recovery order — floor it at startTime. Also push only lastValues.startTime dates (plain field path) instead of whole lastValues rows to keep the aggregation payload small over the capped 31d span.
|
Re: Deep Review round 4 — both P2s addressed in d66c936.
Accepted — this supersedes my round-3 decline, which missed the carry-in interaction: response-internal ordering (recovery never before the pin it follows) is an API invariant, not chart presentation.
Addressed by pushing only |
On the alert details page, firing/recovery markers were drawn one bucket to the right of the data they belong to: the latest OK marker sat at 7:30 while both the plotted data point and the history table's Evaluation Window showed 7:29. Markers now land on the start of the newest evaluated bucket, lining up with the chart and the table.
The transitions endpoint now emits
bucketStart— the newestlastValues.startTimeacross the window's rows (including group-by rows), falling back tocreatedAt − intervalfor windows withoutlastValues, the same fallback the table uses. The client draws atbucketStart ?? createdAt, so older API responses keep working. Deriving the time server-side fromlastValues(rather than shifting by the alert interval client-side) keeps markers correct when evaluations bucket finer than the interval. Dashboard tile alert annotations use the same endpoint, so they shift consistently.Validated with new integration tests (newest-bucket derivation, empty-
lastValuesfallback, group-by max, carry-in pin at range start) and unit tests for the annotation mapping; full unit suites and thealertHistoryintegration suite pass.