Back to home page

EIC code displayed by LXR

 
 

    


Warning, /swf-monitor/docs/ALARM_QUEUE.md is written in an unsupported language. File is not indexed.

0001 # Alarm Queue
0002 
0003 The alarm system is the operations queue for ePIC production: the set of
0004 raised conditions that need a response, each with a lifecycle from raise to
0005 clear, a per-subscriber feed with read state for the people and agents who
0006 follow it, and an automated responder that acts on selected alarm classes.
0007 This document specifies those three extensions of the alarm system described
0008 in [alarms.md](alarms.md). They build on the action stream
0009 ([ACTION_STREAM.md](ACTION_STREAM.md)) and notice routing
0010 ([NOTICE_ROUTING.md](NOTICE_ROUTING.md)).
0011 
0012 ## Roles of the three systems
0013 
0014 - **The alarm system** holds the queue. A raised condition is an alarm event;
0015   the event carries the condition's lifecycle and its response record. The
0016   dashboard at `/alarms/` is the shared view of every raised condition.
0017 - **The action stream** is evidence and record. Detect modules read it (with
0018   PanDA and Rucio) to decide whether a condition is raised, and every
0019   lifecycle transition and every response action is logged on it as an
0020   incident, so Mattermost channels, external feeds, and reports receive alarm
0021   incidents by subscription.
0022 - **Notice routing** delivers. The responder is a push plugin; announcements
0023   reach channels through subscriptions.
0024 
0025 Admission to the queue is a detect module with a threshold, in code, in git.
0026 A condition enters the queue only by being detected. The responder never
0027 creates queue items.
0028 
0029 ## Lifecycle
0030 
0031 An alarm event is one condition on one subject (`dedupe_key`). Its lifecycle
0032 is a sequence of transitions, recorded in an `AlarmTransition` table (event,
0033 kind, time, actor, detail). The engine originates the detection transitions;
0034 the web tier, REST actions, and the responder originate the rest. Every
0035 transition is recorded through one endpoint (Data), which also logs it as an
0036 incident, so a transition and its incident cannot diverge.
0037 
0038 | Transition | Written by | Meaning |
0039 |---|---|---|
0040 | `raised` | engine | condition detected; the event is created |
0041 | `renotified` | engine | condition persists past the renotify interval |
0042 | `acknowledged` | person or agent | someone has taken the item |
0043 | `assigned` | person | the item is handed to a named subscriber |
0044 | `response_proposed` | responder | a diagnosis and proposed action are attached |
0045 | `response_taken` | ops agent, via the responder or a person | the action was executed |
0046 | `verified` | responder | the action's effect was checked |
0047 | `escalated` | engine | raised and unacknowledged past the escalation interval |
0048 | `cleared` | engine | condition no longer detected |
0049 
0050 The event row keeps its current state as a summary of the latest transitions
0051 (`acknowledged_by`, `assigned_to`, `escalated_at`, `clear_time`), and the
0052 transitions are its history. A `renotified` transition is written when the
0053 renotify interval has elapsed since the later of `raised` and the previous
0054 `renotified`, independently of whether email is enabled or sent; the email
0055 bundle keeps its own `last_notified` stamp. Acknowledgement and assignment are
0056 actions on the dashboard and through REST; the response transitions carry a
0057 response record: the diagnosis, the proposed action, who approved it, what was
0058 done, and what the verification found.
0059 
0060 Every transition is also logged on the action stream as an incident
0061 (`alarm_raised`, `alarm_acknowledged`, `alarm_response_taken`, `alarm_cleared`,
0062 and so on) with the alarm name, the subject, the severity, and the dashboard
0063 URL as attributes. The engine does not boot Django; it posts its transitions
0064 to the endpoint, which records them and logs the incidents. Email
0065 notification is unchanged.
0066 
0067 ## Feeds
0068 
0069 A feed is a subscriber's view of the queue with read state. A subscriber is a
0070 person or an agent, identified by account. Everyone sees every raised
0071 condition by default; a subscription filter is available and is used for
0072 agents, where it is an authorization boundary (a responder subscribes to the
0073 alarm classes it may act on and sees nothing else).
0074 
0075 Read state is one row per (subscriber, event) holding the id of the last
0076 transition that subscriber has read. The event is unread for a subscriber
0077 when its latest transition is newer than that pointer, so every transition
0078 (a renotify, a response, a clear) makes the item unread again and moves it
0079 to the top of the feed, ordered by latest transition. The event's history is
0080 the transition list, expandable in place. The unread count is a count over
0081 the join.
0082 
0083 - **People** use a feed page in swf-monitor: reverse-time by latest
0084   transition, unread rendering, mark-read and mark-unread per item, mark-all,
0085   unread-only and severity filters carried in the URL, and the same
0086   keyboard navigation as the Logs page. Marking an item read updates only
0087   that subscriber's pointer.
0088 - **Agents** use two MCP tools on their own service account: list unread
0089   (never marks anything) and mark read. For an agent, unread is its work
0090   queue: it lists, handles, and marks read when handled; an item it did not
0091   mark stays unread and is handled again on the next pass.
0092 
0093 Read state is private to the subscriber. The dashboard shows the shared state
0094 of the queue and no read state.
0095 
0096 ## Response
0097 
0098 The responder is an LLM operation dispatched for the alarm classes it
0099 subscribes to: on `raised`, and on `renotified` when the event carries no
0100 response transition yet, so a dispatch lost to an outage is retried at the
0101 next renotify. It runs on the wrangler agent
0102 ([WRANGLER_AGENT.md](WRANGLER_AGENT.md)): the notice-routing push plugin
0103 `alarm-responder` enqueues one worker per matching incident, keyed on the
0104 event, and the agent's `alarm_respond` handler runs the doer with the
0105 swf-monitor MCP tools. The responder never holds a production credential; a
0106 privileged action is a request to the production ops agent through the
0107 task-operation queue, which executes it, verifies the result, and records the
0108 verified outcome as it does for any operator request.
0109 
0110 The responder has three modes, set per alarm class in SysConfig and visible
0111 on the dashboard:
0112 
0113 | Mode | Behaviour |
0114 |---|---|
0115 | `listen` | the responder is not dispatched |
0116 | `advise` | the responder diagnoses and attaches `response_proposed` (diagnosis, proposed action, reasoning); a person approves on the dashboard or through the bot, and the approval executes the action |
0117 | `act` | for reversible actions only: the responder requests the action, waits for the ops agent's verified outcome, attaches `response_taken` and `verified`, and the transitions notify subscribers after the fact |
0118 
0119 Reversible means the action has an inverse and a false positive costs delay
0120 rather than data: pausing tasks (resume is the inverse) is the first such
0121 action. Kill, retry, and anything touching data are never taken in `act`
0122 mode.
0123 
0124 Guardrails apply in every mode: the tool surface exposed to the responder is
0125 the authorization boundary (pause and resume, nothing else, in the first
0126 version); a per-hour cap on responder-initiated actions per alarm class; every
0127 proposal, approval, action, and verification is a transition and an
0128 action-stream incident; and the dispatch is skipped when the event already
0129 carries a response transition, so a renotify does not restart the analysis.
0130 
0131 ## Escalation
0132 
0133 An event raised and unacknowledged past the alarm's escalation interval gets
0134 an `escalated` transition, which re-flags every subscriber and is an incident
0135 subscribable by a Mattermost channel or an email digest. The interval is a
0136 per-alarm parameter alongside the existing renotify interval.
0137 
0138 ## Detect modules
0139 
0140 The queue is only as useful as its detect modules. The first three:
0141 
0142 - **Black hole** — a site or queue on which jobs fail at a high rate with
0143   short wall time over a window; the subject is the site, and the response is
0144   to pause the tasks routed to it.
0145 - **Catalog-sync freshness** — the nightly `catalog_sync` summary record
0146   missing or old on the action stream.
0147 - **Payload-fetch rate** — `fetch_payload_log` error rate over a window on
0148   the action stream.
0149 
0150 Each is one `detect(client, params)` module and one alarm entry, per
0151 [alarms.md](alarms.md).
0152 
0153 ## Data
0154 
0155 - `AlarmTransition` — event, kind, time, actor, detail (JSON). Written only
0156   by the web tier: a token-authenticated endpoint, `/api/alarms/transitions/`,
0157   records a transition and logs its action-stream incident in one request.
0158   The engine posts its detection transitions to it; the dashboard, REST
0159   actions, and the responder write through the same path.
0160 - `AlarmFeedState` — subscriber, event, last read transition. Unique per
0161   (subscriber, event).
0162 - Alarm entry parameters gain `escalation_interval` and `responder_mode`.
0163 - SysConfig gains the responder's per-class caps.
0164 
0165 ## Delivery sequence
0166 
0167 1. Transitions table and detection transitions from the engine; every
0168    transition logged as an action-stream incident; acknowledgement and
0169    assignment on the dashboard. Existing alarms and email unchanged.
0170 2. Feed state, the feed page, and the two MCP tools.
0171 3. The black-hole detect module.
0172 4. The responder in `advise` mode on the black-hole class, with the
0173    dashboard approval path executing through the ops agent.
0174 5. `act` mode for pause, after the advise record shows the proposals are
0175    what an operator would have done.
0176 
0177 ## Status
0178 
0179 Design. Nothing in this document is implemented.