[Alerting] Alert flyout: labeled enums, tz-aware timestamps, named source, linkified runbooks (SRE2/OBS1) - #2825
Conversation
PR Reviewer Guide 🔍(Review updated until commit 91851ca)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to 91851ca Explore these optional code suggestions:
Previous suggestionsSuggestions up to commit 189fc2e
Suggestions up to commit 27c97c6
Suggestions up to commit dc844aa
|
|
Persistent review updated to latest commit 27c97c6 |
27c97c6 to
189fc2e
Compare
|
Persistent review updated to latest commit 189fc2e |
…e colors Foundation for the 2026-08-25 UX audit fixes. Pure additions — no existing behavior changes here; the alert surfaces migrate onto these in follow-ups. - enum_labels.ts: translatable SEVERITY_LABELS / STATE_LABELS plus getters, so surfaces stop interpolating raw lowercase wire values (CLAR1). Also centralizes the EMPTY_VALUE placeholder, which had drifted between em dash and triple-hyphen on the same table (CLAR4). - time_format.ts: formatTimestamp() honors the dateFormat:tz advanced setting and names the zone it rendered in, so two engineers reading one incident no longer see two unlabeled wall-clock times (CLAR9). Returns the placeholder instead of moment's "Invalid date" for bad input. - alert_colors.ts: severity/state/kind colors derived from euiThemeVars instead of literal light-theme hex, which rendered near-invisible in dark mode and drifted per component (M6). Refs: CLAR1, CLAR4, CLAR9, M6 Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
…alth
Rule status and health are a different vocabulary from alert state, so
`getStateLabel` is the wrong tool for them: OpenSearch-alerting sends
lowercase tokens (`active`, `disabled`, `no_data`) while the AD and
forecaster side sends display-ready sentences ("Running", "Awaiting data
to init"). A single map over both would either leave the tokens raw or
re-case the sentences and corrupt their wording.
`getMonitorStateLabel` translates only the seven tokens that need it and
passes anything already cased through unchanged, so the rules table and
the rule-detail flyout can stop rendering `active` / `no_data` next to an
alerts table that now reads "Active".
Additive; no existing caller changes behaviour.
Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
…SLO page SRE2: annotation values that are safe http/https URLs now render as clickable EuiLink (external, target=_blank, rel=noreferrer) via the new reusable LinkifyAnnotation helper; unsafe schemes (javascript:, data:, etc.) and non-URLs fall back to plain text. Applied in the alert detail flyout annotations list and the SLO metadata panel annotation column. OBS1: the alert flyout 'Open SLO' action now navigates to the SLO detail page (#/slos/<slo_id>) in the SLO app via application.navigateToApp, instead of the Rules definition list; monitor/rule deep-links remain same-app hash navigation. Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
The "Source rule" description row fell back to the action label when no `monitor_name` label was present, so an SLO burn-rate alert rendered "Open SLO" twice — once as the header button, once as the source's "name" — and titled the row "Source rule" while pointing at an SLO. Resolve the source name from the labels the backends actually emit (`monitor_name` / `slo_name` / `slo_id` / `alertname` / `monitor_id`) and title the row "Source SLO" for SLO alerts. Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
The follow-up switched the two source-pivot tests from clicking
getByText('Open SLO'/'Open rule') to getByTestId('alertDetailOpenSource'),
which dropped the only assertions that the header button still renders the
action label. Re-assert the button's text so the button-vs-row-name
distinction this fix introduced stays covered.
Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
Live validation against the observability stack surfaced the flyout
disagreeing with the table it was opened from, for the same alert:
- the table reads "Error" / "Medium", the flyout read the raw backend
enums "error" / "medium" (both header chips and the detail list);
- the table's Started tooltip reads "Aug 21, 2026 @ 11:59:56 PDT", the
flyout's Started read "8/26/2026, 11:00:18 AM" — `toLocaleString()`
never names the zone it rendered in, so two readers comparing an
incident timeline see two different "start" times with no way to
tell them apart;
- missing values used a hand-written em dash rather than the shared
placeholder, so the two surfaces could drift apart again.
Routes all three through the shared primitives (`getStateLabel`,
`getSeverityLabel`, `formatTimestamp`, `EMPTY_VALUE`) instead of
re-deriving them here, so the flyout and the table cannot diverge.
`formatTimestamp` also replaces the `Invalid date` moment would print
for an unparseable timestamp with the placeholder.
Note: this adds a dependency on the shared-primitives PR, which merges
first in this batch — the alerts table and the monitor-detail flyout
already consume the same module.
Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
Signed-off-by: Ashish Agrawal <ashisagr@amazon.com>
189fc2e to
91851ca
Compare
|
Persistent review updated to latest commit 91851ca |
What & why
The alert-detail flyout contradicted the alerts table it was opened from, for the same alert: State/Severity shown as raw enums (
active/critical), timestamps viatoLocaleString()with no timezone, and the 'Source' row repeating the action label 'Open rule' instead of naming the rule/SLO. Now: Title-cased chips, zone-labelled timestamps (… PDT), the source row names the actual rule/SLO, URL-shaped annotations (runbooks) linkify as external links (SRE2), and SLO burn-rate alerts pivot to the SLO detail page (OBS1).Findings: SRE2, OBS1, plus flyout↔table parity (State/Severity/timestamps/empty-glyph).
Before / after
Before / after
Flow
Testing
alert_detail_flyout.test.tsx+linkify_annotation.test.tsx: 27 tests pass. Centrally green.Review
Independent review agent: APPROVE — verified the protocol-based XSS gate on linkify (only http/https), the cross-app SLO pivot, and full flyout↔table parity.
Regression check
The before/after above is a full-viewport capture, so adjacent components on the same surface are visible and unchanged — the diff is scoped to what's called out. Cross-component safety is also verified centrally: this change is file-disjoint from the other in-flight audit fixes (no file overlap, so it merges cleanly with them), and the affected plugin test suites pass with 0 new type errors vs
main. Aside from the merge-order note below, it can be reviewed, merged, and reverted independently.Dependency
Stacked on #2826 (shared primitives). This branch includes #2826's files so it builds and tests standalone in CI; merge #2826 first, then a rebase drops those files from this diff.