Skip to content

alert_transitions API returns incomplete transitions (raises missing) #1155

Closed

Description

@ktsaou

Summary

POST /api/v2/spaces/{spaceId}/rooms/{roomId}/alert_transitions returns only part of the alert transitions in the requested window. Transitions into WARNING/CRITICAL are missing far more often than transitions back to CLEAR, so any count of "alerts raised" built on this endpoint undercounts, and raise/clear pairs cannot be matched.

Evidence

Same space and room, same time windows, payload { "after": <s>, "before": <s> } (no node or chart filters):

Window Source Result
last 3h alert_transitions (frontend endpoint) 1,098 transitions in the room; for all azure_monitor.* alerts together: CLEAR→CRITICAL 5, CRITICAL→CLEAR 15, CLEAR→WARNING 9, WARNING→CLEAR 12
last 3h MCP get_alert_transitions, one single azure_monitor.* alert 36 transitions for that alert alone: CLEAR→CRITICAL 18, CRITICAL→CLEAR 18
last 24h alert_transitions (frontend endpoint) 6,942 transitions in the room; for azure_monitor.* alerts: CLEAR→CRITICAL 7 vs CRITICAL→CLEAR 27, CLEAR→WARNING 10 vs WARNING→CLEAR 43

One alert alone has more raises in 3 hours than the endpoint returns for all alerts of that collector, and in every window the endpoint returns many more clears than raises.

Other observations

  • The response has no old.duration, so time spent in the previous state cannot be read directly.
  • Adding an unsupported contexts field to the payload changes the result to a 100-row, unfiltered response instead of being ignored or rejected.

Expected

All transitions in the window are returned (or the response says it is truncated and supports paging), and request fields that are not supported are rejected or ignored without changing the result.

Impact

Frontend cards that count raised alerts over a time range (alerts raised over time, raised/resolved counts, mean time to resolve, noisiest resources) undercount, especially for flapping alerts.

Activity

  1. self-assigned this
    on Nov 5, 2026
  2. car12o commented on Nov 5, 2026

    @car12o

    Fixed and deployed. The endpoint now returns every transition in the window, newest first. It pages them and reports a total, and each row now includes old.duration.

    Why raises were missing

    A history response merged two sources:

    • Feed events: only the newest 100, whatever the window, because of feed-svc's lean search page cap.
    • Current state: one row per alert instance from node_instance_alarms, presented as a transition.

    Most instances are CLEAR at any given moment, so the second source was mostly →CLEAR rows, including UNKNOWN→CLEAR initialisations. A flapping alert showed up once, as its last clear. That is how 3h returned 1,098 rows with only 5 CLEAR→CRITICAL. On staging the endpoint covered 119 of 322 transitions over 24h and 147 of 1,763 over 7d, with 4 CLEAR→CRITICAL against 42 real ones.

    The contexts observation was a separate bug. Alarm-processor accepted contexts and forwarded it, but lean search never mapped it, so you got the room's newest 100 events unfiltered. charts was lost the same way: feed-svc had renamed the key, and alarm-processor still sent the old name.

    What callers get now

    • History comes from feed-svc only. There are no current-state rows.
    • page_size is 1–1000 and defaults to 1000. Pass next_cursor back as cursor until it comes back empty. total is the match count across all pages. Paging no longer skips events that share a timestamp.
    • contexts and charts filter. Names must match exactly: ["azure_monitor.*"] matches nothing, so list the full context names.
    • after and before are Unix timestamps in milliseconds.
    • Every row has event_id, which is unique per row (transition_id can repeat), plus units and value_string on old and new.
    • old.duration is the number of seconds spent in the status left. The top-level non_clear_duration is the number of seconds since the alert left CLEAR. Both are omitted when unknown. Events written before 1.29.3 have no old.duration.
    • Lookups by transitions still read stored state, up to 1000 IDs on one page.

    Also found and fixed

    • The room endpoint's database half filtered by space only. Since 1.23.1, anyone who could open a room saw alerts for every node in the space.
    • Lean search replaced the permitted-action filter with the caller's actions, so any space member could read events their role does not allow.
    • On nodes reported by several claims, a de-escalation took the surviving claim's previous state (for example CLEAR→CLEAR). It was dropped from history and from notifications. Those clears now appear and notify.
    • Node-level events were stamped with processing time instead of the agent's transition time, 0–537s off on staging.
    • The cloud-insights get_alert_transitions tool reported truncated results as complete. It now reports "N of total".

    Changes

    Change PR Release
    Scope to the room's nodes; send charts as chart_ids netdata/cloud-alarm-processor-service#604, netdata/cloud-alarm-processor-service#605 1.28.4
    Complete paged history; multi-claim de-escalations netdata/cloud-alarm-processor-service#606 1.29.1
    Agent transition time on feed events netdata/cloud-alarm-processor-service#608 1.29.2
    old.duration, non_clear_duration netdata/cloud-alarm-processor-service#609 1.29.3
    Lean contexts filter and action permissions netdata/cloud-feed-service#275 0.10.1
    Tie-safe lean paging, page cap 1000 netdata/cloud-feed-service#276 0.11.1
    Index Netdata.alert.previous.duration netdata/feed-ontology#99, netdata/cloud-kit#522 (v2.5.0), netdata/cloud-feed-service#279, netdata/cloud-feed-service#280 feed-svc 0.11.2
    Truncation reporting in the MCP tool netdata/cloud-insights-service#372 0.29.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions