What AIOps is
Link to section “What AIOps is”In 30 seconds
Link to section “In 30 seconds”AIOps (artificial intelligence for IT operations) applies statistics, machine learning and, more recently, large language models (LLMs) to the events and telemetry that IT systems emit. The aim is that people see fewer, better-grouped alerts, reach a probable cause sooner, and let safe, repetitive fixes run on their own. Gartner’s glossary keeps the definition narrow: AIOps “combines big data and machine learning to automate IT operations processes, including event correlation, anomaly detection and causality determination”.[1]
In one line: AIOps turns a flood of operational signals into a short list of actionable incidents, and it is only as good as the labels, topology and feedback you give it.
This page is for NOC (network operations centre) and ITOps leads facing alert floods, SREs and on-call engineers, the engineers who feed the event pipeline, and buyers of “AIOps” or “event intelligence” platforms. Beginners can read the first two parts and the cheat sheet. Engineers should go to the labs, and leaders to the decision framework and the judgement call.
At a glance
Link to section “At a glance”| Question | Answer |
|---|---|
| Goal | Fewer, better-grouped, actionable incidents; faster triage; automation that is measured and reversible |
| Typical users | NOC and ITOps teams, SREs, on-call engineers, observability and platform teams, IT service management (ITSM) process owners |
| In scope here | Ingesting and normalising events, deduplication, grouping and inhibition, topology and change correlation, anomaly detection, ranking probable causes, guarded remediation, and evaluation (precision and recall are defined here for the whole Atlas) |
| Out of scope | Telemetry pipelines → ObservabilityOps; incident roles and communications → IncidentOps; the same techniques against attackers → AIOps for Security; training pipelines → MLOps; ITIL processes → ITOps |
| Prerequisites | Working alert rules, named service owners, a list of services and their dependencies, a change log |
| Key outputs | A label contract, correlation and inhibition rules, a topology file, an evaluation scorecard, a remediation allow-list |
| Term status | Established label with contested breadth (see the note above) |
The problem it solves
Link to section “The problem it solves”When one shared component fails, everything that depends on it complains. Alertmanager’s documentation gives the classic example: during a network partition, hundreds of service instances each alert because they cannot reach the database, although one page would do.[8] Researchers call this an alert storm (Scenario 1 has a documented case).[9]
Noise has a human cost. Google’s SRE book states it as a philosophy of paging: “I can only react with a sense of urgency a few times a day before I become fatigued.”[10] In Grafana Labs’ 2026 survey, 30% of respondents named alert fatigue as the biggest obstacle to faster incident response. The survey is a vendor’s, and its respondents chose themselves, so read it as a signal rather than a measurement.[11]
Without event intelligence:
- Duplicate paging. Several teams are woken for one fault, and each starts its own investigation.
- Symptom chasing. Responders work on the loudest alert, not the failing dependency.
- Hidden incidents. A second, unrelated failure disappears inside a storm.
- Manual toil. The same safe fix (rotate logs, restart a stuck worker) is typed by hand at 3 a.m.
What AIOps is not
Link to section “What AIOps is not”- Not operations for AI. Running models and LLM applications is MLOps and LLMOps. AIOps applies AI to IT operations.
- Not observability. Collecting, shaping and storing metrics, logs and traces belongs to ObservabilityOps. AIOps consumes that data.
- Not incident management. Roles, severity, communication and post-incident reviews belong to IncidentOps. AIOps decides what reaches them and with what context.
- Not security analytics. Detecting attackers uses the same techniques against an adversary who adapts. That is AIOps for Security.
- Not autonomous operations. “Self-healing” is a direction, not a state you can buy (see NoOps).
- Not a replacement for good alert rules. Google’s SRE book (2016) says: “We avoid ‘magic’ systems that try to learn thresholds or automatically detect causality.”[10]
- Not root-cause certainty. Tools rank probable causes from a limited menu (Datadog’s Watchdog names four types).[12]
Where AIOps comes from and where it sits
Link to section “Where AIOps comes from and where it sits”Origins and evolution
Link to section “Origins and evolution”Event consolidation is older than the label. A 2024 review describes the “traditional methods” that AIOps set out to improve as “reliant on manual tasks and rule-based approaches”.[7] IBM describes its Tivoli Netcool/OMNIbus event console as consolidating information from separate network management platforms and automating the processing of alerts.[13] What changed in the 2010s was scale (cloud, microservices, many monitoring tools) and the hope that learning could replace some hand-written rules.
| When | Milestone | Why it matters |
|---|---|---|
| July 2016 | A Gartner research note by Colin Fletcher on “AIOps Platforms” opens its summary with “Algorithmic IT operations platforms”[2] | An early use of the AIOps label, as a platform market |
| 2019–2021 | Microsoft researchers present AIOps challenges at ICSE;[4] a mapping study finds 62% of contributions treat failure-related tasks;[5] a white paper calls the field “emerging”[14] | A research community forms around failure management |
| 2020 | Peer-reviewed industry papers on alert storms[9] and on incident management at Microsoft[15] | Evidence from production systems, not only demos |
| 2023 | Microsoft studies LLMs for root-causing more than 40,000 incidents;[16] Dell completes its acquisition of Moogsoft on 17 September 2023[17] | LLMs enter the field; vendors consolidate |
| 2025 | Elastic agrees to acquire Keep, an open-source AIOps company (7 May);[18] Gartner renames its market event intelligence solutions (as quoted by Selector);[6] Forrester publishes its AIOps Wave[3] | The label is contested, but the category persists |
| 2025–2026 | Agent benchmarks such as AIOpsLab and ITBench;[19][20] managed anomaly-detection services retire (see tooling) | Agents are evaluated; engines churn |
Gartner’s 2026 market guide (5 May 2026)[21] defines event intelligence solutions, as quoted by BigPanda, as “tools that apply artificial intelligence (AI) and data analytics to augment, accelerate, and automate responses to signals or events detected from digital services”.[22]
Glossary and mental model
Link to section “Glossary and mental model”| Term | Meaning on this page | Example |
|---|---|---|
| Event | Any recorded change of state that may matter to operations | “Disk at 85%” |
| Alert | An event that a rule judged worth someone’s attention | HighErrorRatio firing for checkout-api |
| Incident | An unplanned interruption or degradation that people manage as one piece of work | “Checkout failing in eu-1” |
| Fingerprint | A stable identity for an alert, usually a hash of its labels | Repeats share one |
| Deduplication | Collapsing repeats of the same fingerprint into one alert | 20 re-notifications become 1 |
| Enrichment | Adding owner, service, tier, runbook and recent changes to an event | team=payments, a runbook link |
| Grouping (correlation) | Putting alerts that share a cause into one incident | Database alert plus its callers’ error alerts |
| Inhibition | Muting notifications for some alerts while another alert is firing[8] | “Cluster unreachable” mutes per-service alerts |
| Silence | A time-limited, matcher-based mute that a person sets[8] | Planned maintenance |
| Topology | Which services, hosts and networks depend on which | api → db |
| Change event | A record that something was altered: a deploy, configuration change or feature flag | checkout-api v2026.10.16-3 |
| Anomaly | A value or pattern unlike the learned normal one | Night traffic at 2.5 times its usual level |
| Baseline and seasonality | The learned normal, including daily and weekly cycles | Lower weekend traffic |
| Probable cause | The component or change ranked most likely to explain a group | “orders-db”, “deploy v3” |
| Ground truth label | What responders confirm at close: which alerts belonged together, what the cause was | “Grouped correctly: yes” |
| Precision and recall | The share of a system’s flags or merges that were right, and of true cases it found; F1 is their harmonic mean (Metrics) | P = 0.58, R = 1.00 |
| TP, FP, FN | True positive (a right flag or merge), false positive (a wrong one), false negative (a miss) | Merging two incidents: FP |
| Guarded remediation | An automated fix that is allow-listed, rate-limited, verified and reversible | Rotate logs on a full volume |
| SLO and burn rate | A service level objective is a target for a user-visible measure; “Burn rate is how fast, relative to the SLO, the service consumes the error budget”[23] (see SRE) | 99.9% of checkouts succeed |
| CMDB | Configuration management database: the ITSM record of components and their relations | A (often stale) topology source |
| MTTx (MTTA, MTTR) | Mean time to acknowledge, repair or resolve; see the caveats in IncidentOps | MTTR |
Mental model: a funnel with a feedback loop. Signals become events, events become alerts, alerts become incidents, and people confirm or correct the grouping. Every stage throws information away; the craft is to discard noise, keep signal, and know by measuring which of the two you lost.
Diagram source (Mermaid)
flowchart TB S["Signals: metrics, logs, traces, checks"] --> E["Events (thousands)"] E --> D["Deduplicate and normalise"] D --> A["Alerts (hundreds)"] A --> G["Group, inhibit, enrich"] G --> I["Incidents (a few)"] I --> R["People act and close"] R --> L["Labels: right group? right cause?"] L -.->|"monthly scorecard: tune rules and models"| G L -.->|"fix noisy rules"| A classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029 classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029 class S,E,A,I neutral class D,G,R core class L decision
Text equivalent: signals become thousands of events; deduplication and normalisation leave hundreds of alerts; grouping, inhibition and enrichment leave a few incidents. People act, close them and record whether grouping and cause were right. Those labels feed a monthly scorecard that tunes grouping, and point at noisy alert rules to fix.
How AIOps relates to other Ops
Link to section “How AIOps relates to other Ops”AIOps sits between the teams that produce telemetry and the teams that respond to incidents. Where a boundary below is the Atlas’s own choice rather than an industry standard, it is marked as an editorial distinction.
| Neighbour | Shared ground | What AIOps adds | Read it for |
|---|---|---|---|
| ObservabilityOps | Telemetry, labels, alert rules | Correlation and anomaly models over that data | Pipelines, cardinality, cost of telemetry |
| IncidentOps | Incidents, on-call, MTTx | What reaches responders, grouped and enriched | Roles, severity, communications, MTTR caveats |
| SRE | Alert quality, toil | ML grouping on top of SLO-based alerting | SLOs, error budgets, burn-rate alerts |
| ITOps | Event, incident and change processes, the CMDB | Machine analysis inside those processes | ITIL practices, change enablement |
| ServiceOps | Service catalogue and ownership | Uses ownership and tiers to route and rank | Service ownership model |
| AIOps for Security | Same techniques | Editorial distinction: faults here, adversaries there | Base rates, adversarial evaluation |
| MLOps | Model lifecycle | Applies models; owns no training platform | Registries, drift, retraining |
| AutomationOps | Remediation runbooks | Decides when an automated action may fire | Automation safety in general |
| ChatOps | Where incidents surface | Context posted into the channel | Chat interfaces and bots |
Diagram source (Mermaid)
flowchart TB OBS["Telemetry (ObservabilityOps)"] --> AIO CHG["Changes and deploys"] --> AIO TOPO["Topology and owners (ServiceOps, CMDB)"] --> AIO AIO["AIOps: correlate, detect, rank, guard"] AIO --> INC["IncidentOps: people respond"] AIO --> AUTO["AutomationOps: safe fixes"] INC -.->|"labels"| AIO AIO -.-|"editorial boundary"| SEC["AIOps for Security"] AIO -.-|"model practices"| ML["MLOps"] classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029 classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029 class AIO core class OBS,CHG,TOPO,INC,AUTO,ML neutral class SEC risk
Text equivalent: telemetry (ObservabilityOps), changes and deploys, and topology and owners (ServiceOps, CMDB) flow into AIOps, which correlates, detects, ranks and guards. It sends incidents to IncidentOps and allow-listed fixes to AutomationOps; IncidentOps returns labels. An editorial boundary separates AIOps for Security; MLOps supplies model-lifecycle practices.
Principles and operating model
Link to section “Principles and operating model”Charter and principles (this Atlas’s proposal)
Link to section “Charter and principles (this Atlas’s proposal)”No body publishes an official AIOps manifesto; this charter derives from the evidence on this page.
Mission: reduce the attention that operational events cost people, without hiding a single incident that matters, and make every automated decision explainable and reversible.
- Rules before learning. Start with deduplication, explicit grouping, inhibition and SLO-based alerting (Google’s stance, quoted above). Add learning where labelled incidents show that rules fail.
- Never drop silently. Every grouped, inhibited or suppressed alert stays queryable; every suppression has an owner, a reason and an expiry date.
- Measure both kinds of error. Wrong merges (precision) and splits or misses (recall) both cost something; compression alone is a vanity metric.
- Context beats cleverness. Topology, ownership, changes and calendars explain more alerts than any algorithm can infer from alert text. Dynatrace says of its own engine: “time correlation alone is not sufficient”.[24]
- People own production changes. Machines may run allow-listed, reversible, rate-limited actions; anything else is a suggestion for a person.
- Explain every decision. Each grouping and each probable cause shows why: shared labels, a topology path, a change, a model score.
- Own what is portable. The label contract, rules, labelled incidents and evaluation harness belong to you; engines get replaced (see tooling).
Non-goals: fully autonomous operations, replacing on-call engineers, or claiming certainty about root causes.
Building blocks
Link to section “Building blocks”| Block | Job | Main inputs | Typical failure |
|---|---|---|---|
| Ingest and normalise | Map events from every monitor to one schema | Webhooks, APIs, log streams | Fields that differ between tools |
| Label contract | Guarantee that every alert carries service, team, severity, the affected cluster, the evaluating server and a runbook |
Alert rules, target labels, external labels | Missing labels, or one label with two meanings, break grouping and inhibition |
| Deduplicate | Collapse repeats by fingerprint | Fingerprints | Fingerprints that include volatile labels, such as a pod name |
| Enrich | Add owner, tier, runbook and recent changes | Service catalogue, CMDB, change log | Stale ownership data |
| Context stores | Hold topology, changes and calendars | Tracing-derived dependencies, CI/CD, change records | Missing shared infrastructure (networks, DNS) |
| Correlate | Group alerts into incidents | Rules, time windows, topology, learned similarity | Over-merging or over-splitting |
| Detect anomalies | Flag deviations that no static rule describes | Metric history, seasonality | Business events mistaken for faults |
| Rank probable causes | Order the likeliest components and changes | Topology, change log, model scores | Confident answers from a narrow menu |
| Act | Route, notify, open tickets, run guarded fixes | Routing rules, runbooks, runner | Over-privileged runners; unverified actions |
| Feedback and evaluation | Store labels; score precision, recall and accuracy | Responder corrections | No labels, so no measurement |
Roles, ownership and RACI
Link to section “Roles, ownership and RACI”AIOps fails more often for lack of an owner than of an algorithm. Name an event-intelligence owner, accountable for the pipeline’s precision, recall and backlog; in a small organisation this is part of an SRE’s or observability engineer’s job.
| Activity | Event-intelligence owner | Service owners | On-call responders | Platform team | Change authority |
|---|---|---|---|---|---|
| Define and enforce the label contract | A | R | I | R | I |
| Maintain topology and ownership data | C | A/R | I | R | I |
| Change grouping or inhibition rules | A/R | C | C | C | I |
| Roll out an anomaly detector to a service | A | R | C | C | I |
| Label groupings and causes at incident close | C | C | R | I | I |
| Approve a class of automatic remediation | C | R | C | C | A |
| Monthly evaluation scorecard | A/R | I | C | C | I |
| Select or replace a platform | R | C | C | C | A |
R = responsible, A = accountable, C = consulted, I = informed; “platform team” includes observability engineers. With an ITIL change process, approving a remediation class is usually a standard change (see ITOps).
Lifecycle of a correlation or detection policy
Link to section “Lifecycle of a correlation or detection policy”Treat every grouping rule, inhibition rule, anomaly detector and remediation playbook as a policy with a lifecycle. The states below are this Atlas’s proposal; “shadow mode” means the policy runs and is scored, but changes nothing that people see.
Diagram source (Mermaid)
stateDiagram-v2 direction TB [*] --> Proposed Proposed --> Shadow: tests pass Shadow --> Canary: precision and recall meet targets Shadow --> Proposed: misses or bad merges Canary --> Active: one or two services stay healthy Canary --> Shadow: complaints or a missed incident Active --> Review: monthly score drops or topology changes Review --> Active: re-tuned Review --> Retired: no longer earns its keep Retired --> [*]
Text equivalent: a Proposed policy enters Shadow when its tests pass. Shadow leads to Canary if precision and recall meet targets, or back to Proposed after misses or bad merges. Canary becomes Active if one or two services stay healthy, or returns to Shadow after complaints or a missed incident. Active goes to Review when the monthly score drops or topology changes; Review re-tunes it back to Active or retires it.
- Day 0 (design). Inventory and baseline alert sources (roadmap); write the label contract and a first topology file; choose rules first.
- Day 1 (rollout). Run new policies in shadow mode against a few weeks of labelled incidents, then enable them service by service, starting with volunteers.
- Day 2 (operation). Topology, traffic and rules drift. Review the scorecard monthly, re-label disputed incidents, retire dead rules, and re-evaluate after every major platform change.
Operating model and governance
Link to section “Operating model and governance”- Everything as code. Grouping rules, inhibition rules, detector settings and playbooks live in version control and change by
pull request. CI lints every alert rule, runs
promtool test rulesfor important ones andamtool config routes testfor routing (Artefact 1).[25][26] - Three change classes. Routing and grouping changes need the owning team’s review. Suppression and inhibition need evidence and an expiry date. A new class of automatic remediation needs the change authority’s approval and a rollback plan.
- Feedback at incident close. Ask responders two one-click questions: were these alerts correctly grouped? and was the probable cause right? Without these labels you cannot compute precision or recall. PagerDuty’s documentation shows why the capture point matters: its learned grouping learns from manual merges and moves; “Only manual merges and unmerges in the PagerDuty web app influence the algorithm”, merges made through the API do not, and alert titles rewritten by Event Orchestration also count.[27]
- Cadence. A weekly noise review (the ten noisiest rules and actions taken), a monthly scorecard, and a quarterly review of platform fit.
Architecture and workflow
Link to section “Architecture and workflow”Reference architecture
Link to section “Reference architecture”The architecture is vendor-neutral: an all-in-one platform implements most layers itself, a composable stack assembles them from separate tools, and the trust boundaries stay the same.
Diagram source (Mermaid)
flowchart TB SRC["Alert sources: metric rules, log and trace signals, probes"] SRC --> N["Normalise; check label contract"] MH["Metric history"] --> AD["Anomaly detection"] N --> DD["Deduplicate and enrich"] DD --> CO["Group, inhibit and route"] AD --> CO T["Topology and owners"] --> CO CO --> RC["Rank probable causes"] CH["Change log and calendar"] --> RC RC --> IM["Incident tool and paging"] IM --> CHAT["Chat channel"] CO -.->|"allow-listed alerts only"| RR["Remediation runner"] RR -.->|"outcome; page on failure"| IM IM -.->|"labels at close"| LB["Labelled incidents"] LB -.->|"tune"| CO classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029 class N,DD,CO,AD,RC core class RR risk class SRC,MH,T,CH,LB,IM,CHAT neutral
Text equivalent: alert sources (metric rules, log and trace signals, probes) are normalised and checked against the label contract, deduplicated and enriched, then grouped, inhibited and routed, with input from anomaly detection (which reads metric history) and from topology and owners. Groups are ranked for probable cause using the change log and calendar, then reach the incident tool and paging, which posts to chat. Routing also sends allow-listed alerts, and only those, straight to the remediation runner, the risk point, before any ranking; the runner reports its outcome and pages on failure. Labels captured at close tune grouping.
Trust boundaries. Four places deserve security review. (1) Ingest endpoints: anything that can post an event can create or
hide an incident, so authenticate webhooks in both directions. (2) The alert manager’s own API: Prometheus’s security model says
that anyone who can reach the Alertmanager HTTP endpoint can “create, modify and delete silences”, and that it serves /api/v2
with Access-Control-Allow-Origin: *, so any website opened in a browser that can reach it can call the API.[28] One
request can silence an outage. (3) The remediation runner holds production credentials: give it the narrowest rights per
allow-listed action. (4) An LLM that reads alert text sees attacker-controllable strings: treat them as untrusted input (see
LLMOps).
| Option | Strengths | Limits | Fits when |
|---|---|---|---|
| Built into your observability platform | Shares the vendor’s topology and telemetry; little integration work | Sees mainly that vendor’s data; lock-in | Most telemetry already lives in one platform |
| Standalone event-intelligence platform | Cross-tool correlation across many monitors | Integration and data-mapping effort; another bill | Many monitoring tools; a central NOC |
| Composable open source (for example Alertmanager, Keep, Event-Driven Ansible) | Control, portability, no per-event pricing | You own operations, upgrades and evaluation | Strong platform team; mostly Prometheus-style alerts |
| Build your own models | Fits unusual data | Highest cost; needs ML skills and labels | Very large estates with data scientists; research settings |
End-to-end workflow
Link to section “End-to-end workflow”The sequence follows one incident; the alt block is the exception path, a wrong grouping or cause.
Diagram source (Mermaid)
sequenceDiagram
autonumber
participant M as Monitors
participant E as Event intel
participant I as Incident tool
participant O as On-call
M->>E: 40 alerts in 4 min
Note over E,I: dedup, group by topology, attach change
E->>I: 1 incident, cause: orders-db
I->>O: page DB owner
alt grouping or cause wrong
O->>I: split, merge, fix cause
else grouping and cause right
O->>I: confirm, work from the cause
end
O->>I: resolve, confirm labels
I->>E: labelled incident for evaluation
Text equivalent: monitors send 40 alerts in four minutes to the event-intelligence layer, which deduplicates and groups them by topology and attaches the recent change, then sends one incident (probable cause: orders-db) to the incident tool, which pages the database owner. If the grouping or cause is wrong, the engineer splits, merges or corrects it; otherwise the engineer confirms and works from the cause. The engineer resolves and confirms the labels, and the labelled incident returns for evaluation.
A corrected wrong grouping is a training signal; an unnoticed one teaches the system to repeat the mistake. An allow-listed fault takes a third path: the alert goes straight to the runner, which pages a person if its checks or its fix fail (see the guarded-remediation gate).
Practices, methods and tools
Link to section “Practices, methods and tools”Core practices and playbooks
Link to section “Core practices and playbooks”The practices are in the order in which they usually pay off; the first four need no machine learning.
| Practice | Goal | Trigger | Owner | Output | Verification |
|---|---|---|---|---|---|
| 1. Label contract | Every alert can be routed, grouped and inhibited | New alert rule or monitor | Service owner | Labels service, team, severity, remediation, the affected cluster, the evaluating prometheus; annotation runbook_url |
A linter fails CI on every rule; Alertmanager measures the compliant share |
| 2. Deduplicate | One alert per fingerprint per episode | Repeat notifications | Event-intelligence owner | Stable fingerprints that exclude volatile labels | Re-notifications per alert ≈ 1 |
| 3. Group and inhibit | One notification per cause | Several alerts share a service, cluster or dependency | Event-intelligence owner | group_by; guarded inhibition rules |
Pairwise precision and recall on labelled incidents |
| 4. Topology and change correlation | Link symptoms to failing dependencies and recent changes | Any group with more than one service | Service owners and platform team | Topology file; change events with service labels | Share of incidents with the right cause in the top 3 |
| 5. Anomaly detection where rules cannot reach | Catch deviations no static threshold describes | Seasonal or business metrics | Service owner | Seasonal baseline, calendar, minimum duration | Precision and recall on injected or labelled anomalies |
| 6. Probable-cause ranking | Point responders at the right component first | Every incident | Event-intelligence owner | Ranked candidates with the evidence for each | Top-k cause accuracy |
| 7. Guarded remediation | Remove robotic pages | A known fault with a reversible fix | Automation owner, approved by the change authority | Allow-listed playbook, throttle, verification, rollback | Success, rollback and override rates |
| 8. Feedback and evaluation | Know whether 1–7 work | Incident close; monthly | Event-intelligence owner | Labels; scorecard | Trend in the scorecard metrics |
Practice 1 is the foundation. Grouping by service fails when half the rules call it app. Inhibition by cluster misbehaves
in two ways. When the label is absent, Alertmanager treats it as an empty value, so “if all the label names listed in equal are
missing from both the source and target alerts, the inhibition rule will apply”.[29] And when one label carries two
meanings, where the rule was evaluated and which cluster is affected, two unrelated alerts can share a value. The
worked runbook shows both hiding an outage. Keep the meanings in
separate labels, cluster (affected) and prometheus (evaluating), as Artefact 1 does.
Practice 4 exploits a common cause of outages. Google’s SRE book (2016) says: “SRE has found that roughly 70% of outages are due to changes in a live system.”[30] The figure is Google’s and its method unpublished, but attaching recent changes to every incident is cheap and often decisive. Datadog’s Watchdog RCA names version changes as one of its four root-cause types, alongside traffic increases, AWS instance failures and full disks.[12]
Practice 7 starts from a paging principle: “If a page merely merits a robotic response, it shouldn’t be a page.”[10] Robotic responses are candidates for automation, behind the guarded-remediation gate.
Methods and frameworks: rules, statistics, machine learning and language models
Link to section “Methods and frameworks: rules, statistics, machine learning and language models”No standard defines AIOps methods; the literature organises them by task: anomaly detection, failure prediction, root-cause analysis and remediation.[5][7]
| Technique | Good at | Fails when | Documented example |
|---|---|---|---|
| Exact-match grouping on chosen fields | Predictable, explainable grouping | Labels are inconsistent | PagerDuty Content-Based Alert Grouping, “without the need to train an algorithm”;[31] Alertmanager group_by[29] |
| Tags plus time window | Cross-tool grouping | Unrelated faults overlap in time | BigPanda correlation patterns combine source systems, tags, a time window and an optional filter[32] |
| Inhibition | Muting known downstream symptoms | Labels are missing (see the runbook) | Alertmanager inhibition rules[8] |
| Topology-aware correlation | Linking symptoms to a failing dependency | Topology is stale or omits shared infrastructure | Dynatrace’s fault-tree analysis over its Smartscape topology[24] |
| Change correlation | Pointing at the recent deploy | Changes are not recorded with service labels | Datadog Watchdog RCA (version changes)[12] |
| Statistical baselines | Seasonal metrics such as traffic | Holidays, campaigns, slow drifts | Modified z-score with median and MAD;[33] STL (seasonal-trend decomposition using Loess);[34] Grafana’s PromQL anomaly bands[35] |
| Forecasts (predictive alerts) | Resources that run out steadily: disks, quotas | Bursty use; clean-up jobs; counters | Prometheus predict_linear;[36] node_exporter’s filesystem alerts[37] |
| Unsupervised ML | Many dimensions, no labels | Nobody can say why a point is anomalous | scikit-learn’s Isolation Forest, and its distinction between outlier and novelty detection[38] |
| Learned grouping from feedback | Adapting to how a team actually groups alerts | Feedback is sparse or inconsistent | PagerDuty Intelligent Alert Grouping learns from manual merges and moves[27] |
| Statistical log analysis | Explaining a spike in log volume | Logs lack structure | Elastic’s log rate analysis, log pattern analysis and change point detection[39] |
| LLMs | Summarising, classifying and drafting from incident text | No ground truth; untrusted input; hallucination | Microsoft studies on root-causing incidents[16][40] |
When rules beat machine learning. Prefer rules when the failure has a clear symptom (an SLO burn rate, an error ratio), people know the topology, no labelled incidents exist to evaluate a model, a wrong suppression would be costly, or on-call engineers must predict the system’s behaviour at 3 a.m. Google’s SRE book allows one exception to its simple rules: detecting “unexpected changes in end-user request rates”.[10] Its workbook judges alert rules on precision, recall, detection time and reset time,[23] the same attributes this page uses for models.
When learning earns its place. When many tools produce inconsistent alerts, metrics are strongly seasonal, topology is too large or fast-changing to maintain by hand, and enough labelled incidents exist to show in shadow mode that a model beats the rules.
Diagram source (Mermaid)
flowchart TB
Q1{"Pages follow symptoms and SLOs?"} -->|"no"| R1["Fix alert rules first (SRE)"]
Q1 -->|"yes"| Q2{"Alerts carry service, team, cluster?"}
Q2 -->|"yes"| Q3{"Storms from shared dependencies?"}
Q2 -->|"no"| R2["Label contract, dedup, group_by"]
Q3 -->|"yes"| R3["Inhibition plus topology correlation"]
Q3 -->|"no"| Q4{"Seasonal metrics hide faults?"}
Q4 -->|"no"| Q5{"100+ labelled incidents, rules failing?"}
Q4 -->|"yes"| R4["Seasonal baselines plus calendars"]
Q5 -->|"yes"| R5["Shadow-trial learned grouping"]
Q5 -->|"no"| R6["Stop: rules are enough"]
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
class Q1,Q2,Q3,Q4,Q5 decision
class R2,R3,R4,R5 core
class R1,R6 risk
Text equivalent: if pages do not yet follow symptoms and SLOs, fix the alert rules first. If alerts lack service, team and cluster labels, introduce a label contract, deduplication and grouping. If storms come from shared dependencies, use inhibition plus topology correlation; otherwise, if seasonal metrics hide faults, use baselines with calendars; otherwise, with about 100 labelled incidents and failing rules, shadow-trial learned grouping, and without them stop: rules are enough. The 100 is this Atlas’s rule of thumb, not a published figure.
Predictive alerting and failure prediction
Link to section “Predictive alerting and failure prediction”Notaro and colleagues divide failure management into “failure prevention, online failure prediction, failure detection, root cause
analysis (RCA) and remediation”; the papers they map predict disk, hardware and software failures.[5] In daily operations
the most defensible form is a forecast of exhaustion: disk space, quotas, connection pools. Prometheus’s predict_linear “predicts
the value of time series t seconds from now, based on the range vector v, using simple linear regression” and “should only be used
with gauges”.[36] The node_exporter project’s filesystem alert shows the careful pattern: free space already low, a
6-hour trend reaching zero within the horizon, a writable filesystem, and the condition held for an hour.[37]
Example status: PromQL adapted from the node_exporter 1.12.1 mixin (critical variant, checked 2026-10-17); not executed.
# Alert rule expression, with for: 1h in the rule: under 20% free AND the
# 6-hour trend reaches zero within 4 hours AND the filesystem is writable.
(
node_filesystem_avail_bytes{mountpoint="/var/log"}
/ node_filesystem_size_bytes{mountpoint="/var/log"} * 100 < 20
and
predict_linear(
node_filesystem_avail_bytes{mountpoint="/var/log"}[6h], 4 * 3600
) < 0
and
node_filesystem_readonly{mountpoint="/var/log"} == 0
)
- A straight line extrapolates the window. A burst of writes predicts exhaustion; a clean-up job predicts plenty. The mixin names two causes and two remedies. Scheduled clean-up jobs “may not align with the default time window of these alerts. This can cause these alerts to start flapping”; its remedy is a shorter alert horizon (the 4 hours above), which leaves the job time to run. Short-lived fluctuation is the other cause: a longer prediction window (the 6 hours of history) can “reduce false positives caused by temporary spikes”.[37]
- Evaluate it like any detector. On past exhaustion events, weigh the lead time gained over a static threshold against false forecasts per week; ten minutes gained with weekly flapping is noise.
- Forecast resources, not users. For user-visible symptoms an SLO burn-rate alert already forecasts budget exhaustion (SRE). Learned failure prediction (disks, for example) is a learned detector: shadow mode and labelled outcomes first.
How the learning techniques work: logs, similarity and causal graphs
Link to section “How the learning techniques work: logs, similarity and causal graphs”Logs become templates first. A log line mixes a fixed message with variables, so analysis starts by mining templates: Drain3
turns “user davidoh logged in” and “user eranr logged in” into user <:*:> logged in, and opens a new template when too few tokens
match (similarity threshold 0.4 by default).[41] Detectors then count each template per time window or session and flag
unusual counts (PCA, invariant mining, clustering, classifiers),[42] or learn the normal order of templates and flag changed
sequences.[43] The evidence is sobering. An ICSE 2022 study found that training-data choice, grouping, class balance and
noise significantly affected the evaluation of five deep-learning detectors, which “do not always work well”;[44] an FSE 2024
study found simple detectors competitive with advanced ones on common benchmark data sets: flagging template types never seen in
training sufficed on one, comparing template counts on another.[43] Start with
new-template and template-rate alerts; score anything cleverer as in Lab 3.
Learned grouping is a similarity score plus a threshold. Documentation shows three kinds of evidence. Shared fields: Splunk
ITSI’s Smart Mode weighs “category” fields (a status) against “text” fields (a description) and can split by service
first.[45] Text: PagerDuty compares alert summaries by default and warns that a larger time window raises “the chance of
overgrouping”.[27] Co-occurrence: Moogsoft’s Tempus compares arrival patterns with the Jaccard index; its documentation rules it out for
slow degradation.[46] Lab 2’s related() functions are the hand-written version. Ask which fields, weights and window decide a
merge, then score it with pairwise precision and recall.
Graph and causal root-cause analysis rank candidates. Lab 2 picks an alerting service none of whose dependencies alert. Graph methods generalise this: take the graph from topology or learn a causal one from metrics (PC or GES in PyRCA), then score each node, for example by a random walk that assumes “a metric that is highly correlated with the anomaly metrics is more likely to be the root cause”.[47] An ASE 2024 evaluation of 21 such methods for microservices found that “no method stands out in all situations” and that synthetic results “may not accurately reflect their performance in real systems”.[48] Treat the output as a ranked list with evidence, scored by top-k accuracy.
Tooling landscape (as of October 2026)
Link to section “Tooling landscape (as of October 2026)”Examples are documented capabilities checked on 2026-10-16, not endorsements.
| Category | Job | Examples (verified) | Selection notes |
|---|---|---|---|
| Alert routing and grouping | Deduplicate, group, inhibit, silence, route | Prometheus Alertmanager 0.34.1 (17 September 2026)[49] | Free and predictable; rule-based only |
| Open-source alert management and AIOps | Unify alerts from many tools; deduplicate, correlate, run workflows | Keep 0.54.3 (9 September 2026), “The open-source AIOps and alert management platform”[50] | Elastic announced an agreement to acquire Keep in May 2025; it would “remain open source”[18] |
| Statistical detection in the query language | Seasonal bands as recording and alerting rules | Grafana’s PromQL anomaly-detection framework[35] | Most strategies need 24–26 hours of data; a drop to zero needs a separate rule |
| Event intelligence in incident platforms | Group alerts, pause transient alerts, orchestrate events | PagerDuty Intelligent and Content-Based Alert Grouping, Auto-Pause, Event Orchestration[27][31][51][52] | Learned grouping comes with the PagerDuty AIOps add-on or certain plans (packaging changes) |
| Standalone event-intelligence platforms | Cross-tool correlation | BigPanda (correlation patterns);[32] Dell APEX AIOps Incident Management, formerly Moogsoft (acquired by Dell on 17 September 2023)[17][53] | Integration effort; check the limits (BigPanda caps an incident at 300 correlated alerts) |
| Built into observability and ITOM platforms | Correlation and cause analysis on the vendor’s own topology | Dynatrace root-cause analysis;[24] Datadog Watchdog RCA;[12] Elastic AIOps Labs;[39] Splunk ITSI Event Analytics (correlation searches, aggregation policies, episodes)[54] | Strongest where that vendor already sees most of your telemetry |
| Event-driven automation | Run playbooks on events, with throttling | Event-Driven Ansible: ansible-rulebook 1.3.2[55] | Runner credentials are the main risk |
| Libraries | Build or study algorithms | scikit-learn outlier detection;[38] Drain3 (log templates);[41] Salesforce PyRCA (root-cause analysis)[47] | Salesforce’s Merlion time-series library was archived on 11 March 2026[56] |
Engines churn; plan for it. Managed services retire and libraries get archived:
| Service or project | Status | Source |
|---|---|---|
| Amazon Lookout for Metrics | AWS ended support in October 2025 | AWS blog[57] |
| Azure AI Anomaly Detector | No new resources since 20 September 2023; retired on 1 October 2026 | Microsoft Learn[58] |
| Amazon DevOps Guru | Closes to new customers on 29 October 2026; existing customers until 30 September 2027 | AWS documentation[59] |
| Salesforce Merlion | Repository archived on 11 March 2026 | GitHub[56] |
The lesson is principle 7, not “avoid managed services”: keep what you need to replace an engine and prove the replacement no worse.
Selection criteria. Beyond the weighted worksheet, ask whether every suppressed alert stays queryable and whether pricing penalises context.
Automation and AI: language models and agents
Link to section “Automation and AI: language models and agents”LLMs have found real work in incident handling, mainly reading and writing text. Microsoft researchers evaluated LLMs for recommending root causes and mitigations on more than 40,000 incidents, with incident owners judging the output.[16] Microsoft’s RCACopilot gathers diagnostics, predicts a root-cause category with an explanation, and reports “RCA accuracy up to 0.766”; its diagnostic-collection module had run in more than 30 teams for over four years, its LLM component in one incident-management team for several months.[40] A 2025 paper reports that its system proposed changes to 1,174 alert rules at an anonymised company, and SREs accepted 375 (32%).[60]
The evidence on autonomy is thin. ITBench, peer-reviewed at ICML 2025, built “an initial set of 102 real-world scenarios” and found that “agents powered by state-of-the-art models resolve only 11.4% of SRE scenarios”; the models were those of early 2025.[20] Newer tests measure something narrower. Artificial Analysis’s ITBench-AA gives agents an offline snapshot of 59 Kubernetes incidents and scores the diagnosis by “average precision at full recall”; the best listed model scored 56.2% (checked 16 October 2026).[61] Diagnosing from a snapshot is not resolving a live system, and leaderboards change monthly, so neither number licenses unsupervised action. AIOpsLab injects faults so that agents can be evaluated before anyone trusts them.[19]
Practical rules for LLMs in operations:
- Start read-only. Summaries, timelines, similar-incident search and runbook retrieval carry little risk if a person reads them.
- Treat alert and log text as untrusted input. Never let model output reach a shell or an API without an allow-list.
- Evaluate like any other policy. Measure top-k cause accuracy and wrong suggestions on labelled incidents, in shadow mode.
- Mind the data. Redact customer data and secrets before incident text leaves your boundary (PrivacyOps); token spend belongs in FinOps for AI.
AIOps in practice
Link to section “AIOps in practice”Reference implementation
Link to section “Reference implementation”Design. A composable, vendor-neutral start for a team with Prometheus-style alerting: a label contract that a linter enforces and Alertmanager measures, Alertmanager for grouping and guarded inhibition, a topology file in Git, a normalised event schema with change events, and a guarded remediation runner. Assumptions: Linux hosts, Prometheus 3.x (3.15.0 was released on 24 September 2026[62]), Alertmanager 0.34.x,[49] pint 0.89.x,[63] ansible-rulebook 1.3.x[55] on the Alertmanager host, and a separate incident tool that accepts webhooks. Constraints: no machine learning yet; every suppression is visible; only one remediation class is automated.
Artefact 1: the label contract and its enforcement. Two labels look alike and must never be merged: the cluster an alert is about and the server that evaluated it.
| Label | Meaning | Set by |
|---|---|---|
service, team |
The service the alert is about, and its owner | Group-level labels in the rule file[64] |
severity, remediation |
page or ticket, the convention shared with IncidentOps and ChatOps; auto or none |
Each rule |
cluster |
The affected cluster | The monitored target’s labels; on an in-cluster server, external_labels as a default |
prometheus |
The server that evaluated the rule | external_labels on every server |
runbook_url (annotation) |
Where the responder starts | Each rule |
External labels never override a label an alert already has,[65] so a rule that watches another cluster keeps that cluster’s name.
Example status: syntax-checked, not executed (requires Prometheus and promtool).
# checkout-rules.yml (in-cluster server): service, team, severity, remediation
# and runbook_url are static; cluster and prometheus come from the server's
# external_labels.
groups:
- name: checkout-api
labels:
service: checkout-api
team: payments
rules:
- alert: HighErrorRatio
expr: |
sum(rate(http_requests_total{job="checkout-api",code=~"5.."}[5m]))
/ sum(rate(http_requests_total{job="checkout-api"}[5m])) > 0.05
for: 5m
keep_firing_for: 5m
labels:
severity: page
database: orders-db
remediation: none
annotations:
summary: "checkout-api 5xx ratio above 5% for 5 minutes"
runbook_url: "https://runbooks.example.com/checkout-api/high-error-ratio"
# prometheus.yml on the in-cluster server of eu-1. The meta-monitoring server sets
# only prometheus: meta because its alerts are about other clusters.
global:
external_labels:
cluster: eu-1 # a default: a cluster label already on an alert wins
prometheus: eu-1
# meta-rules.yml on the meta-monitoring server. Each target of this job carries
# its own cluster label (for example cluster="dev-3"), so the alert names the
# affected cluster. A target without one yields an alert that, by Artefact 2,
# inhibits nothing.
groups:
- name: meta-monitoring
labels:
service: monitoring
team: observability
rules:
- alert: ClusterUnreachable
expr: up{job="cluster-prometheus"} == 0
for: 5m
labels:
severity: page
remediation: none
annotations:
summary: "Prometheus of cluster {{ $labels.cluster }} unreachable for 5m"
runbook_url: "https://runbooks.example.com/monitoring/cluster-unreachable"
Enforcement needs three checks, because each sees only part of the contract. (1) A linter over every rule file. pint’s
rule/label check with required = true flags any alerting rule that lacks a label; it “uses static labels set on alerting or
recording rule” (group-level labels since pint 0.72.0), so it cannot see cluster or prometheus.[66][67]
Its findings are warnings by default and pint lint fails only on bug or worse, so raise the severity.[63] (2) A
configuration check in CI: every server sets prometheus, in-cluster servers set cluster, the meta-monitoring server does
not. (3) A measurement in Alertmanager: the share of current alerts carrying the whole contract, sampled from its API. That share
is the scorecard’s label-contract compliance and maturity level 1’s 95% exit criterion.
Example status: written to the pint documentation for rule/label and alerts/annotation; not executed (requires pint).
# .pint.hcl: run pint lint rules/ in CI.
# Severity "bug" makes a missing label fail the run.
rule {
match {
kind = "alerting"
}
label "service" {
severity = "bug"
required = true
}
label "team" {
severity = "bug"
required = true
}
label "severity" {
severity = "bug"
required = true
values = ["page", "ticket"]
}
label "remediation" {
severity = "bug"
required = true
values = ["auto", "none"]
}
annotation "runbook_url" {
severity = "bug"
required = true
}
}
Example status: executed on 2026-10-17 (Python 3.8.10, PyYAML 5.3.1) against four sample configurations and a saved API response; not run against a live Alertmanager.
"""label_contract.py: check the label contract in two places.
python3 label_contract.py configs prometheus/*.yml # CI: server-level labels
python3 label_contract.py alerts [ALERTS_API_URL] # runtime: compliant share
Standard library, plus PyYAML for the configs check.
"""
import json
import sys
import urllib.request
ALERT_LABELS = ("service", "team", "severity", "remediation", "prometheus")
def check_configs(paths):
import yaml # PyYAML
bad = 0
for path in paths:
with open(path) as f:
glob = (yaml.safe_load(f) or {}).get("global") or {}
labels = glob.get("external_labels") or {}
server = labels.get("prometheus")
if not server:
problem = "no prometheus label"
elif server == "meta" and "cluster" in labels:
problem = "meta-monitoring must not set cluster"
elif server != "meta" and "cluster" not in labels:
problem = "no cluster label"
else:
continue
print(f"{path}: {problem}")
bad += 1
return 1 if bad else 0
def compliant(labels):
if not all(labels.get(k) for k in ALERT_LABELS):
return False
# Meta-monitoring alerts may concern things outside any cluster.
return bool(labels.get("cluster")) or labels.get("prometheus") == "meta"
def check_alerts(url):
with urllib.request.urlopen(url, timeout=10) as resp:
alerts = json.load(resp)
ok = sum(compliant(a["labels"]) for a in alerts)
share = ok / len(alerts) if alerts else 1.0
print(f"alerts={len(alerts)} compliant={ok} share={share:.2f}")
return 0
if __name__ == "__main__":
mode = sys.argv[1] if len(sys.argv) > 1 else ""
if mode == "configs":
sys.exit(check_configs(sys.argv[2:]))
if mode == "alerts":
default = "http://127.0.0.1:9093/api/v2/alerts"
sys.exit(check_alerts(sys.argv[2] if len(sys.argv) > 2 else default))
sys.exit(__doc__)
On the samples, configs flagged a meta-monitoring file with cluster: meta and a file without external labels (exit code 1), and
alerts printed alerts=4 compliant=2 share=0.50. A promtool unit test remains useful as a regression test for one important
rule: it checks only rules that have a test case and never sees external_labels, but its exp_labels must match exactly, so a
dropped label fails the build.[25]
Example status: syntax-checked, not executed (requires promtool).
# checkout-rules.test.yml: run with promtool test rules checkout-rules.test.yml
rule_files:
- checkout-rules.yml
evaluation_interval: 1m
tests:
- interval: 1m
input_series:
- series: 'http_requests_total{job="checkout-api",code="500"}'
values: '0+10x20'
- series: 'http_requests_total{job="checkout-api",code="200"}'
values: '0+90x20'
alert_rule_test:
- eval_time: 15m
alertname: HighErrorRatio
exp_alerts:
- exp_labels:
severity: page
service: checkout-api
team: payments
database: orders-db
remediation: none
exp_annotations:
summary: "checkout-api 5xx ratio above 5% for 5 minutes"
runbook_url: >-
https://runbooks.example.com/checkout-api/high-error-ratio
Artefact 2: grouping, routing and guarded inhibition. The defaults shown (group_wait 30s, group_interval 5m,
repeat_interval 4h) are Alertmanager’s documented defaults, written out for reviewers.[29] Three details carry the safety:
each inhibit rule requires every equal label to be non-empty on the source, so a source without it mutes nothing; rule 1 never
mutes the meta-monitoring server, which watches the alert path itself; and the gateways authenticate Alertmanager by a bearer token
read from a file (credentials_file under http_config → authorization).[29]
Example status: syntax-checked, not executed (requires Alertmanager 0.34.x; Lab 1 runs it).
# alertmanager.yml: grouping, routing and guarded inhibition (Alertmanager 0.34.x).
global:
resolve_timeout: 5m
route:
receiver: ticket-queue
group_by: [cluster, service] # one notification per service per cluster
group_wait: 30s # let related (and inhibiting) alerts arrive
group_interval: 5m
repeat_interval: 4h
routes:
- matchers: ['remediation="auto"'] # allow-listed classes go to the runner...
receiver: eda-remediation
continue: true # ...and still reach a ticket or page
- matchers: ['severity="page"']
receiver: oncall-pager
- matchers: ['severity="ticket"']
receiver: ticket-queue
inhibit_rules:
# 1. A cluster is unreachable: mute the per-service symptoms in that cluster.
- source_matchers:
- alertname="ClusterUnreachable"
- cluster=~".+" # guard: no cluster, mutes nothing
target_matchers:
- alertname!="ClusterUnreachable"
- prometheus!="meta" # never mute the meta-monitoring alerts
equal: [cluster]
# 2. A database is down: mute error and latency symptoms of services that use it.
- source_matchers:
- alertname="DatabaseDown"
- cluster=~".+" # guard
- database=~".+" # guard
target_matchers: ['alertname=~"HighErrorRatio|HighLatency"']
equal: [cluster, database]
receivers:
- name: oncall-pager
webhook_configs:
- url: https://incident-gateway.example.com/hooks/alertmanager
http_config:
authorization: # Bearer by default; file mode 0400
credentials_file: /etc/alertmanager/secrets/incident-gateway
- name: ticket-queue
webhook_configs:
- url: https://ticket-gateway.example.com/hooks/alertmanager
http_config:
authorization:
credentials_file: /etc/alertmanager/secrets/ticket-gateway
- name: eda-remediation
webhook_configs:
- url: http://127.0.0.1:5050/alerts # rulebook on this host (loopback)
send_resolved: false
The residual risk is an observer-side partition. If the meta-monitoring server loses its own route to eu-1 while eu-1’s
Prometheus still reaches Alertmanager, ClusterUnreachable{cluster="eu-1"} fires and rule 1 mutes eu-1’s genuine alerts; the only
page is about the monitoring path. So fire the source only when two independent vantage points agree (for example up == 0 from
the meta server and a failed probe from a second location), and make amtool alert query --inhibited cluster=eu-1 the first
step of that alert’s runbook.
Protect Alertmanager’s API as well (security controls).
Artefact 3: a topology file. This is this Atlas’s minimal format, not a standard. Generate it from tracing data where you can and review it by hand. List shared infrastructure explicitly, because faults there fan out across services that never call each other (Lab 2 shows the cost of leaving it out).
Example status: syntax-checked; a data file, nothing to execute.
services:
web: {team: storefront, tier: 1, depends_on: [checkout-api]}
checkout-api: {team: payments, tier: 1,
depends_on: [orders-db, cache, payments-gw]}
payments-gw: {team: payments, tier: 1, depends_on: [payments-db]}
worker: {team: fulfilment, tier: 2, depends_on: [queue, orders-db]}
shared_infrastructure:
net-zone-a: {owner: network, carries: [cache, queue, orders-db]}
Artefact 4: a normalised event. Anything that leaves Alertmanager, or arrives from another monitor, is mapped to one schema
before correlation. The correlation block records who decided what, so that decisions can be audited and evaluated.
Example status: JSON syntax-checked; the schema name is this Atlas’s own.
{
"schema": "atlas.ops-event/v1",
"fingerprint": "3f6c2a9d1b7e4c08",
"source": "prometheus/eu-1",
"status": "firing",
"starts_at": "2026-10-16T09:14:30Z",
"alertname": "HighErrorRatio",
"service": "checkout-api",
"team": "payments",
"environment": "production",
"cluster": "eu-1",
"severity": "page",
"runbook_url": "https://runbooks.example.com/checkout-api/high-error-ratio",
"recent_changes": ["deploy checkout-api v2026.10.16-3 at 2026-10-16T09:02:11Z",
"config net-zone-a acl-118 at 2026-10-16T08:47:05Z"],
"correlation": {"group_id": null, "probable_cause": null, "decided_by": null}
}
Change events fill recent_changes. A deploy’s last step records the change with the alerts’ service value and a version
(OpenTelemetry’s counterpart is service.version).[68] For an alert or a group, the changes of the preceding hour to
its services, their dependencies and the shared infrastructure under them (Artefact 3) are attached, the alerting services’ own
first. The hour and the order are this Atlas’s starting values; tune them on change-caused incidents.
Example status: executed on 2026-10-17 (Python 3.8.10, PyYAML 5.3.1): record against a local test receiver, attach on four
sample changes; not run in a CI system.
"""change_events.py: record deploys as change events; attach them to alert groups.
python3 change_events.py record SERVICE VERSION [URL] # last step of a deploy
python3 change_events.py attach topology.yml changes.jsonl group.json [MINUTES]
Standard library, plus PyYAML to read the topology file (Artefact 3).
"""
import json
import os
import sys
import urllib.request
from datetime import datetime, timedelta, timezone
FMT = "%Y-%m-%dT%H:%M:%SZ"
def record(service, version, url=None):
event = {
"schema": "atlas.change-event/v1",
"kind": os.environ.get("CHANGE_KIND", "deploy"),
"service": service, # the same value as the alerts' label
"version": version,
"environment": os.environ.get("ENVIRONMENT", "production"),
"by": os.environ.get("CHANGE_ACTOR", "unknown"), # from your CI system
"at": datetime.now(timezone.utc).strftime(FMT),
}
body = json.dumps(event).encode()
print(body.decode())
if url: # the bearer token comes from a file, never the command line
with open(os.environ["CHANGE_LOG_TOKEN_FILE"]) as f:
token = f.read().strip()
req = urllib.request.Request(url, data=body, method="POST", headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"})
urllib.request.urlopen(req, timeout=10).close()
return 0
def nearby(topology, services):
"""The group's services, their dependencies, and shared infrastructure."""
near = set(services)
for name in services:
entry = (topology.get("services") or {}).get(name) or {}
near.update(entry.get("depends_on", []))
for name, entry in (topology.get("shared_infrastructure") or {}).items():
if near & set(entry.get("carries", [])):
near.add(name)
return near
def attach(topology_path, changes_path, group_path, minutes=60):
import yaml # PyYAML
with open(topology_path) as f:
topology = yaml.safe_load(f)
with open(changes_path) as f:
changes = [json.loads(line) for line in f if line.strip()]
with open(group_path) as f:
group = json.load(f)
services = {a["service"] for a in group["alerts"]}
start = min(datetime.strptime(a["starts_at"], FMT) for a in group["alerts"])
since = start - timedelta(minutes=minutes)
near = nearby(topology, services)
hits = [c for c in changes if c["service"] in near
and since <= datetime.strptime(c["at"], FMT) <= start]
hits.sort(key=lambda c: c["at"], reverse=True) # newest first, but
hits.sort(key=lambda c: c["service"] not in services) # own services first
print(f"group {group['group_id']}: {len(hits)} of {len(changes)} changes "
f"in the {minutes} minutes before {start.strftime(FMT)}")
for c in hits:
where = "alerting service" if c["service"] in services else "dependency"
print(f' {c["kind"]} {c["service"]} {c["version"]} at {c["at"]} ({where})')
return 0
if __name__ == "__main__":
args = sys.argv[1:]
if args[:1] == ["record"] and len(args) in (3, 4):
sys.exit(record(*args[1:]))
if args[:1] == ["attach"] and len(args) in (4, 5):
sys.exit(attach(*args[1:4], *[int(m) for m in args[4:]]))
sys.exit(__doc__)
For a group of checkout-api and web alerts from 09:14:30, attach left out a worker deploy (not a dependency) and
yesterday’s checkout-api deploy:
group g-0917: 2 of 4 changes in the 60 minutes before 2026-10-16T09:14:30Z
deploy checkout-api v2026.10.16-3 at 2026-10-16T09:02:11Z (alerting service)
config net-zone-a acl-118 at 2026-10-16T08:47:05Z (dependency)
Artefact 5: guarded remediation. One class is automated: rotate and compress logs when a log volume is nearly full. The rule
sets remediation: auto; Artefact 2 sends such alerts to the rulebook and on to the ticket queue; the rulebook’s allow-list decides
whether anything runs; a second rule pages at 95% regardless. The gate figure below shows where each check lives; the per-host
throttle uses ansible-rulebook’s throttle “to counter event storms”,[69] and runs go one at a time.[70]
Rotation has nothing to undo, so failure pages a person; a class that changes configuration needs a
rollback task there. AutomationOps teaches these controls in general.
Three security facts shape it. The ansible.eda.alertmanager source (collection 2.13.0) is a plain HTTP webhook that performs no
authentication, defaults to localhost, and copies every request header into each event (meta.headers);[71] keep it on
loopback beside Alertmanager. A runner on another host should use ansible.eda.webhook, which checks a bearer token, supports TLS
and mutual TLS, and drops the Authorization header from events; events then arrive under event.payload, and the
insert_hosts_to_meta filter must supply the hosts.[72][73] And “You cannot limit privilege escalation
permissions to certain commands”,[74] so the runner may become only the log owner, never root.
Example status: YAML syntax-checked; keys checked against the Prometheus, ansible-rulebook 1.3.0 and Ansible documentation; not
executed (requires node_exporter, ansible-rulebook with the ansible.eda collection, and an inventory whose host names match the
instance label without its port).
# node-log-rules.yml: one automatable class, and a page that needs no runner.
groups:
- name: node-logs
labels:
service: node-logs
team: platform
rules:
- alert: LogVolumeNearlyFull # allow-listed: a ticket plus the runner
expr: |
1 - node_filesystem_avail_bytes{mountpoint="/var/log"}
/ node_filesystem_size_bytes{mountpoint="/var/log"} > 0.85
for: 10m
labels:
severity: ticket
remediation: auto
annotations:
summary: "/var/log on {{ $labels.instance }} is over 85% full"
runbook_url: "https://runbooks.example.com/node/log-volume"
- alert: LogVolumeCritical # pages whether or not automation ran
expr: |
1 - node_filesystem_avail_bytes{mountpoint="/var/log"}
/ node_filesystem_size_bytes{mountpoint="/var/log"} > 0.95
for: 5m
labels:
severity: page
remediation: none
annotations:
summary: "/var/log on {{ $labels.instance }} is over 95% full"
runbook_url: "https://runbooks.example.com/node/log-volume"
# remediation-rulebook.yml: run with
# ansible-rulebook -r remediation-rulebook.yml -i inventory.yml
- name: Guarded remediation for known, reversible faults
hosts: all
execution_strategy: sequential # one action at a time (the default)
sources:
- ansible.eda.alertmanager:
host: 127.0.0.1 # loopback: the source has no auth
port: 5050
data_alerts_path: alerts
data_host_path: labels.instance # host:port; the source strips the port
rules:
- name: Rotate logs on a nearly full log volume (the allow-list)
condition: >-
event.alert.status == "firing" and
event.alert.labels.alertname == "LogVolumeNearlyFull" and
event.alert.labels.remediation == "auto"
throttle:
once_within: 30 minutes
group_by_attributes:
- event.meta.hosts
action:
run_playbook:
name: playbooks/rotate_logs.yml
- name: Labelled auto but not allow-listed here, so it stays with people
condition: >-
event.alert.status == "firing" and
event.alert.labels.alertname != "LogVolumeNearlyFull"
action:
debug:
msg: "Not on the allow-list: {{ event.alert.labels.alertname }}"
# playbooks/rotate_logs.yml: the checks the rulebook cannot make.
- name: Rotate logs on a nearly full log volume, within caps, then verify
hosts: all # ansible-rulebook limits it to the alert's host
serial: 1
max_fail_percentage: 0
vars:
run_log: /var/lib/eda/rotate_logs.runs # runner host, one line per run
host_daily_cap: 3 # runs per host per day
fleet_hourly_cap: 5 # runs per hour, all hosts: blast radius
max_used_pct: 85 # the alert threshold
gateway_token_file: /etc/eda/secrets/gateway-token
tasks:
- name: Read earlier runs
ansible.builtin.command: cat {{ run_log }}
register: runs
changed_when: false
failed_when: false
delegate_to: localhost
- name: Stop unless both caps allow another run
vars:
today: "{{ now(utc=true, fmt='%Y-%m-%d') }}"
this_hour: "{{ now(utc=true, fmt='%Y-%m-%dT%H') }}"
host_runs: >-
{{ runs.stdout_lines
| select('match', today ~ '.* ' ~ inventory_hostname ~ '$')
| list | length }}
fleet_runs: >-
{{ runs.stdout_lines | select('match', this_hour) | list | length }}
ansible.builtin.assert:
that:
- host_runs | int < host_daily_cap
- fleet_runs | int < fleet_hourly_cap
fail_msg: "Cap reached: no automatic run; the ticket and the 95% page stay"
- name: Record this run before acting
ansible.builtin.lineinfile:
path: "{{ run_log }}"
line: >-
{{ now(utc=true, fmt='%Y-%m-%dT%H:%M:%S') }} {{ inventory_hostname }}
create: true
mode: "0640"
delegate_to: localhost
- name: Act, verify, and page a person on any failure
block:
- name: Rotate and compress within the retention the log owner approved
ansible.builtin.command: >-
logrotate --force --state /var/lib/applog/logrotate.state
/etc/logrotate.d/app
become: true
become_user: applog # the log owner, never root
- name: Verify that usage fell below the alert threshold
ansible.builtin.command: df --output=pcent /var/log
register: usage
changed_when: false
failed_when: >-
usage.stdout_lines[-1] | trim | replace('%', '') | int >= max_used_pct
rescue:
- name: Page a person (rotation has nothing to undo)
ansible.builtin.uri:
url: https://incident-gateway.example.com/hooks/remediation-failed
method: POST
headers:
Authorization: >-
Bearer {{ lookup('ansible.builtin.file', gateway_token_file) }}
body_format: json
body:
host: "{{ inventory_hostname }}"
action: rotate_logs
result: failed
delegate_to: localhost
- name: Fail the run so that the rulebook log shows it
ansible.builtin.fail:
msg: "rotate_logs failed on {{ inventory_hostname }}; a person is paged"
Every automated action passes the same gate. Google’s account of an automated decommissioning job that wiped the disks of its CDN machines explains the gate’s checks: afterwards Google added “more sanity checks—including rate limiting” and made the workflow idempotent.[75]
Diagram source (Mermaid)
flowchart TB
T["Alert with remediation=auto"] --> A{"On the rulebook allow-list?"}
A -->|"no"| H["Stays with people: ticket now, page at 95%"]
A -->|"yes"| C{"Host throttle free? (rulebook)"}
C -->|"no"| H
C -->|"yes"| B{"Daily and fleet caps free? (playbook)"}
B -->|"no"| H
B -->|"yes"| D["Run as the log owner, not root"]
D --> E{"Verified fixed? (playbook)"}
E -->|"yes"| F["Record outcome; alert resolves"]
E -->|"no"| G["Roll back if possible; page a person"]
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
class A,B,C,E decision
class D,F core
class H,G risk
Text equivalent: an alert labelled for automatic remediation must be on the rulebook’s allow-list, pass the rulebook’s per-host throttle, and pass the playbook’s daily and fleet-wide caps; failing any check leaves it with people (a ticket now, a page at 95%). Otherwise the playbook acts as the log owner, not root. A verified fix is recorded and the alert resolves; otherwise the playbook rolls back where possible and pages a person.
Hands-on labs
Link to section “Hands-on labs”Three labs, from configuration to measurement; Labs 2 and 3 were executed and their outputs are verbatim.
Lab 1 (beginner): group and inhibit with Alertmanager
Link to section “Lab 1 (beginner): group and inhibit with Alertmanager”- Objective: see grouping and inhibition work, reproduce the missing-label pitfall, then watch the guard stop it.
- Prerequisites: Linux with
bash,curl,tarandsha256sum; port 127.0.0.1:9093 free; Artefact 2 saved asalertmanager.yml. Run it as a script (bash lab1.sh alertmanager.yml); pasted into a terminal,set -ewould close the shell at the first error. Cost and risk: none; everything binds to localhost. Notification errors (example.com, missing credential files) are expected.
Example status: syntax-checked, not executed (downloads a third-party binary).
#!/usr/bin/env bash
# lab1.sh: run with bash lab1.sh /path/to/alertmanager.yml (Artefact 2)
set -euo pipefail
CONFIG="$(realpath "${1:?usage: bash lab1.sh /path/to/alertmanager.yml}")"
VERSION=0.34.1
TARBALL="alertmanager-${VERSION}.linux-amd64.tar.gz"
BASE="https://github.com/prometheus/alertmanager/releases/download/v${VERSION}"
WORK="$(mktemp -d)" && cd "$WORK"
curl -fsSLO "${BASE}/${TARBALL}"
curl -fsSLO "${BASE}/sha256sums.txt"
grep "${TARBALL}" sha256sums.txt | sha256sum -c -
tar xzf "${TARBALL}" && cd "alertmanager-${VERSION}.linux-amd64"
grep -v '# guard' "$CONFIG" > unguarded.yml # Artefact 2 without its guards
./amtool check-config "$CONFIG" unguarded.yml
./amtool config routes test --config.file="$CONFIG" \
--verify.receivers=oncall-pager severity=page service=checkout-api
cp unguarded.yml active.yml
# Single node: an empty cluster address disables HA mode.
./alertmanager --config.file=active.yml --storage.path=./data \
--web.listen-address=127.0.0.1:9093 --cluster.listen-address="" > am.log 2>&1 &
AM_PID=$!
trap 'kill "$AM_PID"; rm -rf "$WORK"' EXIT # teardown when the script ends
sleep 3
AM="--alertmanager.url=http://127.0.0.1:9093"
# 1. Inhibition as intended: the same cluster label on source and target.
./amtool $AM alert add alertname=ClusterUnreachable cluster=eu-1 severity=page
./amtool $AM alert add alertname=HighErrorRatio cluster=eu-1 \
service=checkout-api severity=page
./amtool $AM alert add alertname=HighErrorRatio cluster=eu-2 \
service=checkout-api severity=page
sleep 5
echo "== active"; ./amtool $AM alert query
echo "== inhibited"; ./amtool $AM alert query --inhibited
# 2. The pitfall: neither alert has a cluster label, so the unguarded rule applies.
./amtool $AM alert add alertname=ClusterUnreachable severity=page
./amtool $AM alert add alertname=EndpointDown service=storefront-probe severity=page
sleep 5
echo "== inhibited, unguarded"; ./amtool $AM alert query --inhibited
# 3. The fix: load the guarded file and ask again.
cp "$CONFIG" active.yml
curl -fsS -X POST http://127.0.0.1:9093/-/reload
sleep 2
echo "== inhibited, guarded"; ./amtool $AM alert query --inhibited
- Expected output:
check-configreportsSUCCESSfor both files, with 2 inhibit rules, 3 receivers and 0 templates (the format in the Alertmanager documentation[29]);routes testprintsoncall-pager. Step 1: active areClusterUnreachable(eu-1) andHighErrorRatio(eu-2); only the eu-1HighErrorRatiois inhibited. Step 2:EndpointDownis inhibited too, although it concerns no cluster. Step 3: it is active again. - Validation: the active eu-2 alert proves that
equal: [cluster]works when the label exists; step 2 shows the documented missing-label behaviour;[29] step 3 shows the guard removing it. With only--inhibited,amtoollists only inhibited alerts.[76] - Troubleshooting:
address already in usemeans another Alertmanager is running; if nothing is inhibited, raise thesleepvalues; readam.logfor configuration errors. - Teardown: automatic: the
trapstops Alertmanager and deletes the working directory. To explore by hand, comment out thetrapline and clean up yourself.
Lab 2 (intermediate): measure correlation quality
Link to section “Lab 2 (intermediate): measure correlation quality”- Objective: compare three grouping strategies on labelled incidents using pairwise precision and recall, then see what a stale topology does.
- Prerequisites: Python 3.8 or later; save the script as
correlation_lab.py. Cost and risk: none.
How it is scored. Every pair of alerts is a decision: the strategy put them in the same group or not, and the ground truth says whether they belong to the same incident. Manning and colleagues present this pair-decision view as an alternative to measures such as purity and normalised mutual information.[77]
| Pair of alerts | Same incident (truth) | Different incidents (truth) |
|---|---|---|
| Same group | TP: a correct merge | FP: a wrong merge |
| Different groups | FN: a missed merge | TN: correctly kept apart |
Pairwise precision = TP / (TP + FP); pairwise recall = TP / (TP + FN).[78] Pairs grow with the square of an incident’s size, so one large incident can dominate both numbers. Report the per-incident over-merge and split counts next to them, as the lab does.
Example status: executed on 2026-10-17 (Python 3.8.10); output below is verbatim.
"""Lab 2: compare three alert-grouping strategies against labelled incidents.
Standard library only. Usage: python3 correlation_lab.py [--drop-edge api:db]
"""
import itertools
import random
import sys
from collections import defaultdict
# Caller -> callees. A failing callee makes its callers alert too.
TOPOLOGY = {
"web": ["api"],
"api": ["db", "cache", "payments"],
"payments": ["payments-db"],
"worker": ["queue", "db"],
"reports": [],
}
# Ground truth: (incident id, root service, start minute, alerts per service).
INCIDENTS = [
("INC-1", "db", 0, {"db": ["DBDown"], "api": ["HighErrorRate", "HighLatency"],
"web": ["HighErrorRate"], "worker": ["JobFailures"]}),
("INC-2", "reports", 2, {"reports": ["DiskFull"]}),
("INC-3", "payments-db", 40, {"payments-db": ["SlowQueries"],
"payments": ["HighLatency"],
"api": ["HighLatency"]}),
("INC-4", "queue", 41, {"queue": ["QueueBacklog"], "worker": ["JobLag"]}),
("INC-5", "cache", 90, {"cache": ["Evictions"]}),
# A shared network fault: not in the service topology,
# and the switch itself is not monitored.
("INC-6", "network", 120, {"cache": ["ConnTimeouts"],
"queue": ["ConnTimeouts"]}),
]
WINDOW = 5 # minutes
def make_events(seed=7):
"""Each alert fires 1-3 times (re-notifications), with minutes of jitter."""
rng = random.Random(seed)
events = []
for inc, _root, start, per_service in INCIDENTS:
for svc, names in per_service.items():
for name in names:
first = start + rng.randint(0, 3)
for repeat in range(rng.randint(1, 3)):
events.append({"t": first + repeat, "service": svc,
"alertname": name, "truth": inc})
return sorted(events, key=lambda e: (e["t"], e["service"], e["alertname"]))
def deduplicate(events, episode_gap=10):
"""Drop repeats of a fingerprint (service + alertname) within episode_gap."""
last_seen, out = {}, []
for e in events:
key = (e["service"], e["alertname"])
if key not in last_seen or e["t"] - last_seen[key] > episode_gap:
out.append(e)
last_seen[key] = e["t"]
return out
def neighbours(topology):
graph = defaultdict(set)
for caller, callees in topology.items():
for callee in callees:
graph[caller].add(callee)
graph[callee].add(caller)
return graph
def group(alerts, related):
"""Join every group with a related member seen within WINDOW minutes.
An alert that matches several groups merges them (it bridges them).
"""
groups = []
for a in alerts:
hits = [g for g in groups
if any(a["t"] - m["t"] <= WINDOW and related(a, m) for m in g)]
if not hits:
groups.append([a])
continue
keep = hits[0]
for other in hits[1:]:
keep.extend(other)
groups.remove(other)
keep.append(a)
return groups
def pair_scores(groups):
tp = fp = fn = 0
members = [(gi, a["truth"]) for gi, g in enumerate(groups) for a in g]
for (g1, t1), (g2, t2) in itertools.combinations(members, 2):
same_group, same_truth = g1 == g2, t1 == t2
tp += same_group and same_truth
fp += same_group and not same_truth
fn += (not same_group) and same_truth
precision = tp / (tp + fp) if tp + fp else 1.0
recall = tp / (tp + fn) if tp + fn else 1.0
total = precision + recall
f1 = 2 * precision * recall / total if total else 0.0
return precision, recall, f1
def probable_cause(g, graph_down):
"""Candidate root: an alerting service whose callees do not alert here."""
alerting = {a["service"] for a in g}
leaves = [s for s in alerting if not (set(graph_down.get(s, [])) & alerting)]
return sorted(leaves)
def report(name, groups, raw_count):
p, r, f1 = pair_scores(groups)
truths = defaultdict(set)
for gi, g in enumerate(groups):
for a in g:
truths[a["truth"]].add(gi)
merged = sum(1 for g in groups if len({a["truth"] for a in g}) > 1)
split = sum(1 for gs in truths.values() if len(gs) > 1)
compr = raw_count / len(groups)
print(f"{name:<20} groups={len(groups):>2} compr={compr:4.1f}x "
f"P={p:.2f} R={r:.2f} F1={f1:.2f} merged={merged} split={split}")
def main():
topology = {k: list(v) for k, v in TOPOLOGY.items()}
if "--drop-edge" in sys.argv:
caller, callee = sys.argv[sys.argv.index("--drop-edge") + 1].split(":")
topology[caller].remove(callee)
print(f"(topology edge {caller} -> {callee} removed: "
"simulating a stale CMDB)")
raw = make_events()
alerts = deduplicate(raw)
print(f"raw events={len(raw)} after dedup={len(alerts)} "
f"true incidents={len(INCIDENTS)}")
graph = neighbours(topology)
strategies = {
"S1 time window only": lambda a, b: True,
"S2 same service": lambda a, b: a["service"] == b["service"],
"S3 topology-aware": lambda a, b: (a["service"] == b["service"]
or b["service"] in graph[a["service"]]),
}
results = {}
for name, rel in strategies.items():
results[name] = group(alerts, rel)
report(name, results[name], len(raw))
print("S3 probable causes:")
roots = {inc: root for inc, root, _s, _a in INCIDENTS}
hits = 0
for g in results["S3 topology-aware"]:
truths = [a["truth"] for a in g]
main_truth = max(set(truths), key=truths.count)
cand = probable_cause(g, topology)
hit = cand == [roots[main_truth]]
hits += hit
print(f" {main_truth}: candidates={cand} truth={roots[main_truth]} "
f"{'OK' if hit else 'MISS'}")
n_groups = len(results["S3 topology-aware"])
print(f"top-1 probable-cause accuracy={hits}/{n_groups}")
if __name__ == "__main__":
main()
Steps. (1) Run python3 correlation_lab.py. (2) Run python3 correlation_lab.py --drop-edge api:db: a CMDB that has lost the
fact that the API calls the database. (3) Set WINDOW to 2, then 15, and re-run.
Expected output (step 1, verbatim):
raw events=22 after dedup=14 true incidents=6
S1 time window only groups= 4 compr= 5.5x P=0.58 R=1.00 F1=0.73 merged=2 split=0
S2 same service groups=13 compr= 1.7x P=1.00 R=0.07 F1=0.12 merged=0 split=4
S3 topology-aware groups= 7 compr= 3.1x P=1.00 R=0.93 F1=0.97 merged=0 split=1
S3 probable causes:
INC-1: candidates=['db'] truth=db OK
INC-2: candidates=['reports'] truth=reports OK
INC-3: candidates=['payments-db'] truth=payments-db OK
INC-4: candidates=['queue'] truth=queue OK
INC-5: candidates=['cache'] truth=cache OK
INC-6: candidates=['queue'] truth=network MISS
INC-6: candidates=['cache'] truth=network MISS
top-1 probable-cause accuracy=5/7
Step 2 changes the S3 line to groups= 8 compr= 2.8x P=1.00 R=0.53 F1=0.70 merged=0 split=2, and probable-cause accuracy falls
to 5/8.
- Validation and interpretation. The time window has the best compression (5.5×) and perfect recall, but merged the database outage with an unrelated full disk and the payments slowdown with an unrelated queue backlog: precision 0.58. Grouping by service never merges wrongly but finds almost nothing (recall 0.07). Topology does best because the data were generated from it, which flatters it. The realistic lessons are the network incident, split because shared infrastructure is missing from the graph, and step 2, where one missing edge cuts recall from 0.93 to 0.53.
- Troubleshooting:
ValueError: list.remove(x)means the--drop-edgepair does not exist (usecaller:calleefromTOPOLOGY); an f-string syntax error means Python is older than 3.6. - Teardown: delete the script; it writes nothing.
Lab 3 (advanced): seasonal anomaly detection against a static threshold
Link to section “Lab 3 (advanced): seasonal anomaly detection against a static threshold”- Objective: compare a static band with a seasonal robust baseline on two weeks of synthetic traffic with four labelled faults and two unlabelled business events (a weekday holiday and a marketing campaign).
- Method: the modified z-score, 0.6745 × (x − median) / MAD, against the same 15-minute slot of the same type of day, flagging
absolute scores above 3.5, the threshold Iglewicz and Hoaglin recommend according to the NIST handbook.[33] As with a
Prometheus
forclause, a flag must hold for five minutes before an alert fires.[64] - Prerequisites: Python 3.8 or later; save the script as
anomaly_lab.py. Cost and risk: none (about 0.1 s of CPU).
Example status: executed on 2026-10-17 (Python 3.8.10); output below is verbatim.
"""Lab 3: static thresholds versus a seasonal robust baseline.
Standard library only. A synthetic request rate, two weeks at 1-minute resolution:
week 1 trains, week 2 is scored. Usage: python3 anomaly_lab.py [--calendar]
"""
import math
import random
import statistics
import sys
DAY = 1440
rng = random.Random(42)
def normal_rate(minute):
"""Daily cycle (low at night, peak mid-afternoon), quieter weekends, noise."""
hour = (minute % DAY) / 60
weekday = (minute // DAY) % 7 < 5
if 6 <= hour <= 22:
base = 200 + 800 * max(0.0, math.sin(math.pi * (hour - 6) / 16))
else:
base = 200
base *= 1.0 if weekday else 0.6
return max(0.0, rng.gauss(base, 0.05 * base + 10))
series = [normal_rate(m) for m in range(14 * DAY)]
# Labelled anomalies in week 2: (name, start minute, length, transform).
W2 = 7 * DAY
ANOMALIES = [
("peak-hour drop to 40%", W2 + 0 * DAY + 14 * 60, 30, lambda v, i: v * 0.4),
("night spike x2.5", W2 + 1 * DAY + 3 * 60, 15, lambda v, i: v * 2.5),
("total outage (zero)", W2 + 2 * DAY + 10 * 60, 20, lambda v, i: 0.0),
("slow 30% decline", W2 + 3 * DAY + 8 * 60, 600,
lambda v, i: v * (1 - 0.3 * i / 600)),
]
truth = set()
for _name, start, length, f in ANOMALIES:
for i in range(length):
series[start + i] = f(series[start + i], i)
truth.add(start + i)
# Two unlabelled business events in week 2: real changes in traffic, not incidents.
HOLIDAY = 11 # a public holiday on a weekday (day 11): weekend-like traffic
for m in range(HOLIDAY * DAY, (HOLIDAY + 1) * DAY):
series[m] *= 0.6
for m in range(W2 + 5 * DAY + 18 * 60, W2 + 5 * DAY + 20 * 60): # a campaign
series[m] *= 1.6
train, test_start = series[:W2], W2
# Detector 1: one static band from the training week (0.1th and 99.9th percentiles).
q = statistics.quantiles(train, n=1000)
low, high = q[0], q[-1]
def static_flag(m):
return series[m] < low or series[m] > high
# Detector 2: robust z-score against the same 15-minute slot of the same day type.
# --calendar tells the detector that day 11 is a holiday (treat it like a weekend).
HOLIDAYS = {HOLIDAY} if "--calendar" in sys.argv else set()
def slot(m):
day = m // DAY
return (day % 7 < 5 and day not in HOLIDAYS, (m % DAY) // 15)
buckets = {}
for m, v in enumerate(train):
buckets.setdefault(slot(m), []).append(v)
baseline = {}
for k, vs in buckets.items():
med = statistics.median(vs)
mad = statistics.median(abs(v - med) for v in vs) or 1.0
baseline[k] = (med, mad)
def seasonal_flag(m):
med, mad = baseline[slot(m)]
# Modified z-score (Iglewicz and Hoaglin): flag when |M| > 3.5.
return abs(0.6745 * (series[m] - med) / mad) > 3.5
def alerts(flag, for_minutes=5):
"""Fire once the flag has held for for_minutes (like Prometheus 'for:')."""
fired, run, out = False, 0, []
for m in range(test_start, len(series)):
run = run + 1 if flag(m) else 0
if run >= for_minutes and not fired:
out.append(m)
fired = True
if run == 0:
fired = False
return out
def matches(m):
"""True if an alert at minute m belongs to a labelled anomaly (10 min grace)."""
return any(s <= m < s + n + 10 for _a, s, n, _f in ANOMALIES)
def evaluate(name, fired):
detected, delays = [], []
for aname, start, length, _f in ANOMALIES:
hits = [m for m in fired if start <= m < start + length + 10]
detected.append(aname if hits else None)
if hits:
delays.append(hits[0] - start)
false = [m for m in fired if not matches(m)]
on_holiday = sum(1 for m in false if m // DAY == HOLIDAY)
precision = (len(fired) - len(false)) / len(fired) if fired else 1.0
recall = sum(d is not None for d in detected) / len(ANOMALIES)
print(f"{name:<18} alerts={len(fired):>3} false={len(false):>3} "
f"(holiday {on_holiday:>2}) P={precision:.2f} R={recall:.2f}")
print(f" delays to first alert (min): {delays}")
for (aname, *_rest), d in zip(ANOMALIES, detected):
print(f" {'caught' if d else 'MISSED':<6} {aname}")
print(f"static band: alert below {low:.0f} or above {high:.0f} requests/min")
evaluate("static band", alerts(static_flag))
evaluate("seasonal robust z", alerts(seasonal_flag))
Steps. (1) Run python3 anomaly_lab.py. (2) Run python3 anomaly_lab.py --calendar, which tells the detector that day 11 is a
holiday.
Expected output (step 1, verbatim):
static band: alert below 84 or above 1129 requests/min
static band alerts= 1 false= 0 (holiday 0) P=1.00 R=0.25
delays to first alert (min): [4]
MISSED peak-hour drop to 40%
MISSED night spike x2.5
caught total outage (zero)
MISSED slow 30% decline
seasonal robust z alerts= 44 false= 34 (holiday 32) P=0.23 R=1.00
delays to first alert (min): [4, 4, 4, 401]
caught peak-hour drop to 40%
caught night spike x2.5
caught total outage (zero)
caught slow 30% decline
With --calendar the seasonal line becomes alerts= 12 false= 2 (holiday 0) P=0.83 R=1.00; nothing else changes.
- Validation and interpretation. A static band wide enough for the daily cycle misses everything except the total outage. The seasonal baseline catches all four faults, the slow decline only after 401 minutes, but without context it fires 34 false alerts, 32 of them on the holiday. One line of calendar data removes all 32; the 2 left come from the marketing campaign, which only a change or event feed could explain.
- Troubleshooting:
AttributeError: module 'statistics' has no attribute 'quantiles'means Python is older than 3.8. - Teardown: delete the script; it writes nothing.
Use cases and scenarios
Link to section “Use cases and scenarios”| Scenario | Context | Method | Trade-offs | Success metric | Pitfall |
|---|---|---|---|---|---|
| 1. Alert storm from a shared dependency | A database, network zone or cluster fails; dozens of services complain | Guarded inhibition plus topology-aware grouping | Wrong labels make inhibition hide real incidents | Pairwise precision and recall; alerts examined per incident | Shared infrastructure missing from the topology |
| 2. Change-induced regressions | Frequent deploys; many outages follow changes | Attach recent changes to each incident; rank recent changes as candidate causes | Needs change events labelled by service | Top-3 cause accuracy on change-caused incidents | Changes made outside CI/CD are invisible |
| 3. Business-traffic anomalies | Seasonal traffic where a 40% drop at peak is invisible to static thresholds | Seasonal baselines with calendars and minimum durations | False alerts on holidays and campaigns; slow drifts detected late | Precision and recall on labelled or injected anomalies | Treating every anomaly as an incident |
| 4. Guarded auto-remediation | A recurring fault with a known, reversible fix | Allow-listed playbook, throttle, verification, rollback | Automation can amplify a mistake across many hosts | Success, rollback and human-override rates | Allow-lists that grow without review |
| 5. LLM-assisted triage | Long incidents with many responders and noisy channels | Summaries, timelines, similar-incident search, draft causes for a person to confirm | Plausible but wrong text; data leakage | Time to engage the right team; rate of wrong suggestions | Letting model output trigger actions |
Scenario 1: a documented case. Zhao and colleagues applied their alert-storm method at a large commercial bank (China
EverBright Bank), reporting storm detection with an F1-score above 0.9 and more than 98% fewer alerts to examine.[9] Microsoft
researchers, after two years of incident management, named “incomplete service/resource dependencies” one of two critical
challenges,[15] the weakness Lab 2’s --drop-edge step exposes.
Scenarios 2 and 3: evidence for the approach, not documented cases. Scenario 2 rests on the change evidence in core practices; Lab 3 shows why Scenario 3 needs calendars and change feeds.
Scenarios 4 and 5: illustrative. Scenario 4 is Artefact 5; Scenario 5 rests on the Microsoft studies in Automation and AI.
Measure, govern, pay
Link to section “Measure, govern, pay”Metrics and KPIs
Link to section “Metrics and KPIs”These definitions apply across the Atlas. Precision is the share of a system’s positive decisions that were right; recall is the share of the true cases it found.[78] For grouping, a decision is a pair of alerts placed together or apart, as in Lab 2.[77] Security detection adds base rates and adversarial testing; see AIOps for Security.
| KPI | Definition and formula | Data source | Pitfall | Review cadence |
|---|---|---|---|---|
| Pairwise grouping precision | TP pairs ÷ (TP + FP pairs) | Labelled incidents | Needs labels; big incidents dominate (Lab 2) | Monthly |
| Pairwise grouping recall | TP pairs ÷ (TP + FN pairs) | Labelled incidents | Same | Monthly |
| Over-merge rate | Groups containing alerts from more than one incident ÷ groups | Labels | Hides the second incident | Monthly |
| Split rate | Incidents whose alerts landed in more than one group ÷ incidents | Labels | Causes duplicate pages | Monthly |
| Missed-incident rate | Confirmed incidents for which no person was notified in time ÷ incidents | Post-incident reviews, customer reports | Rare, so trends are noisy; review every case | Every incident |
| Actionable page rate | Pages that led to a human action ÷ pages | Incident tool | Responders may “act” on noise to look busy | Weekly |
| Compression ratio | Raw alerts ÷ incidents presented | Pipeline counters | Vanity metric without precision and recall | Context only |
| Top-k probable-cause accuracy | Incidents whose confirmed cause is in the top k candidates ÷ incidents with a confirmed cause | Labels | Causes are often multiple; record the main one | Monthly |
| Detector precision, recall and delay | Alert episodes that matched a labelled anomaly ÷ episodes; anomalies caught ÷ anomalies; median minutes to first alert | Labels, injected test anomalies | Unlabelled business events | Monthly |
| Forecast lead time and false forecasts | Median minutes a forecast alert precedes exhaustion (or the static alert); forecasts with no exhaustion per week | Labelled exhaustion events | Clean-up jobs make forecasts flap | Quarterly |
| Label-contract compliance | Alerts carrying every contract label ÷ alerts, sampled from the Alertmanager API (Artefact 1) | label_contract.py alerts |
A label that is present but means the wrong thing still passes | Weekly |
| Remediation success, rollback and override rates | Verified fixes ÷ runs; rollbacks ÷ runs; human overrides ÷ runs | Runner logs | Success that only masks a cause | Monthly |
| Time to engage the owning team | First alert → acknowledgement by the team that fixed it | Incident tool | Spell out which clock you mean; see the MTTx caveats in IncidentOps | Monthly |
The asymmetry that sets targets. On a paging route a split costs a duplicate page, while a wrong merge can hide a second incident: set strict targets for precision and missed incidents (review every miss), a looser one for splits. A ticket-only route can tilt towards recall. Derive the numbers from your own shadow-mode baseline; the research for this page found no credible public benchmarks.
Quality, security, privacy and compliance
Link to section “Quality, security, privacy and compliance”| Risk | Signal | Mitigation | Owner |
|---|---|---|---|
| A suppression or inhibition hides a real incident | Customer-reported incidents; the missed-incident rate | Guarded rules; expiry dates; a monthly review of sampled inhibited alerts | Event-intelligence owner |
| Forged or replayed events create or hide incidents | Unknown sources; spikes from one sender | Authenticate ingest webhooks; allow-list sources; rate-limit per source | Platform team |
| Anyone who reaches the Alertmanager API silences an outage | Silences created by unknown users or from unknown addresses | Network policy on port 9093; basic auth and TLS (--web.config.file, still “experimental”); silences only through an authenticated proxy that records who set them; monthly silence audit[28][79] |
Platform team |
| An over-privileged remediation runner | Broad credentials; shared accounts | One narrow credential per action; separate runner identity; approval for new action classes | Automation owner |
| Prompt injection through alert or log text into an LLM assistant | Odd instructions in summaries | Treat event text as untrusted; no tool access without an allow-list (see LLMOps) | Event-intelligence owner |
| Personal data in events and incident text | User identifiers in log lines | Redact at ingest; set retention; check vendor data location (PrivacyOps) | Service owners |
| Unclear regulatory status of automated control | AIOps actions in critical infrastructure | Legal review (below); decision records | Risk or compliance |
Regulation, briefly and with caveats (as of October 2026). Most AIOps uses carry no high-risk obligations, but two EU duties deserve a check. First, Article 4 of the AI Act (AI literacy, applicable since 2 February 2025) binds deployers of any AI system, whatever its risk class. As amended by the Digital Omnibus on AI (Regulation (EU) 2026/1744, in force since 27 July 2026), deployers “shall take measures to support the development of AI literacy” of their staff.[80][81] Whether a tool is an “AI system” in law is a legal question; a learned correlation engine is more likely to be one than a rule-based one. Second, Annex III lists as high-risk “AI systems intended to be used as safety components in the management and operation of critical digital infrastructure, road traffic, or in the supply of water, gas, heating or electricity”;[82] the Omnibus makes the high-risk obligations for Annex III systems apply from 2 December 2027.[81] If you operate critical digital infrastructure in the EU and an AIOps function could act as a safety component, take legal advice. Mapping AI systems to the Act belongs to ModelOps, and audit evidence to ComplianceOps. Elsewhere, NIST’s AI Risk Management Framework is “intended for voluntary use”, on 7 April 2026 NIST released a concept note for a profile on trustworthy AI in critical infrastructure, and NIST says it is revising AI RMF 1.0.[83]
Auditability. Record for every grouping, suppression and automated action which rule or model, which version, which inputs, and
what a person later confirmed; Artefact 4’s correlation block is a minimal version.
Cost, capacity and sustainability
Link to section “Cost, capacity and sustainability”- Cost drivers. Licences (pricing changes often; get written quotes), integration engineering, the owner’s and service owners’ time, labelling, model compute and LLM tokens (FinOps for AI).
- Unit view. Track cost and triage people-hours per incident presented. Book “pages avoided” as savings only if you can show they were noise.
- Capacity: survive the storm you were built for. A correlation layer is busiest when everything else is failing. Alertmanager
warns that
group_interval“also sets the context timeout for the notification pipeline”, so a slow receiver can get notifications cancelled.[29] BigPanda caps an incident at 300 correlated alerts,[32] and PagerDuty’s learned grouping only adds alerts to incidents under 24 hours old.[27] Load-test with a replayed storm. - Sustainability. The footprint is usually small next to the telemetry it reads; keep model training and LLM calls proportional to measured value (GreenOps).
Assurance of the operating model
Link to section “Assurance of the operating model”- A heartbeat that bypasses correlation. The always-firing Watchdog alert and its external checker (IncidentOps, Lab 2) catch a dead pipeline, not wrong grouping.
- Missed-incident review. Every post-incident review asks: did the event pipeline hide, delay or misroute anything?
- Suppression audit. The monthly sample of inhibited and suppressed alerts and silences (checklists), including who created each silence.
- Drift signals. Alert volume per service against its baseline, the age of topology entries, and label-contract compliance.
- Evaluation history. Keep the monthly scorecard in version control, so that a platform change can be compared with the past.
When things go wrong
Link to section “When things go wrong”Common failures and troubleshooting
Link to section “Common failures and troubleshooting”| Symptom | Likely cause | Diagnosis | Remediation | Prevention |
|---|---|---|---|---|
| Customers report an outage, but nobody was paged | Over-broad inhibition or suppression; missing or ambiguous labels | amtool alert query --inhibited; amtool silence query[76][26] |
Fix the labels or guard the rule; page manually | Guarded inhibit rules; label linting; the heartbeat; a suppression audit |
| Two teams paged for one fault | Over-splitting: a topology gap or inconsistent service names | Compare group IDs for the incident’s alerts | Add the edge; normalise the labels | Generate topology from traces; enforce the contract |
| One incident contains unrelated faults | Window too wide; learned grouping drifted | A drop in pairwise precision | Narrow the window; add label constraints; reset or retrain the learner | Shadow-mode evaluation before every change |
| Anomaly alerts on holidays and campaigns | No calendar or change context | False alerts cluster on dates | Add calendars and campaign feeds | A detector review each quarter |
| Slow degradation never alerts | The baseline absorbs gradual drift | Compare with the same slot last month | Add SLO burn-rate alerts (see SRE) | Keep SLO alerts outside the anomaly layer |
| Auto-remediation runs every few minutes | The fix masks the cause; throttle missing | Runner logs | Disable the action class; page the owner | Throttle plus a daily cap and escalation |
| The probable cause is always “the database” | A hub node in the topology, or a narrow menu of causes | Cause accuracy by service | Weight by recent changes; fix the topology | Evaluate top-k accuracy monthly |
| Notifications delayed or cancelled during storms | Pipeline overload; receiver slower than group_interval |
Alertmanager logs | Raise group_interval; scale receivers |
Storm replay tests |
Worked runbook: the inhibition rule that silenced an outage
Link to section “Worked runbook: the inhibition rule that silenced an outage”Scenario (illustrative; the mechanism is documented). A team’s first label contract took cluster only from external_labels,
and its meta-monitoring Prometheus had none. That server raises EndpointDown for a storefront synthetic probe, without a cluster
label, and ClusterUnreachable for a forgotten development cluster whose scrape target has no cluster label either. The unguarded
inhibit rule uses equal: [cluster]; with the label missing from both alerts, Alertmanager applies it.[29] Customers report
failed checkouts 25 minutes later.
Diagram source (Mermaid)
flowchart TB
S["Source: ClusterUnreachable, no cluster label"] --> R{"Unguarded rule: equal cluster"}
T["Target: EndpointDown probe, no cluster label"] --> R
R -->|"before: empty equals empty"| X["Inhibited: outage hidden"]
S --> G{"Guarded rule: source needs cluster=~'.+'"}
G -->|"after: source does not match"| N["Probe pages"]
F["Wrong fix: external_labels cluster=meta"] -.->|"both alerts get meta: still equal"| X
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
class R,G decision
class X,F risk
class N core
class S,T neutral
Text equivalent: a ClusterUnreachable source and an EndpointDown probe both lack a cluster label. Before the fix, the unguarded rule finds the two empty values equal and inhibits the probe, hiding the outage. After it, the guarded rule needs a non-empty cluster on the source, the source does not match, and the probe pages. The tempting wrong fix, external label cluster=meta on the meta-monitoring server, gives both alerts the value meta, so the probe stays inhibited.
-
Declare and page by hand. Do not wait for the pipeline. Follow the incident process in IncidentOps.
-
Is the alert there at all?
amtool --alertmanager.url=http://127.0.0.1:9093 alert query alertname=EndpointDownreturns nothing; adding--inhibitedreturns it.[76] Now you know that it is muted, not missing. -
What is muting it? Silences:
amtool silence query. Inhibitions: the v2 API returns, withactive=false, only silenced or inhibited alerts, and each alert’sstatus.inhibitedBylists the fingerprints of the alerts that inhibit it.[84][85]Example status: syntax-checked, not executed (requires a running Alertmanager and
jq).curl -s 'http://127.0.0.1:9093/api/v2/alerts?active=false' \ | jq -r '.[] | [.labels.alertname, (.labels.cluster // "-"), (.status.inhibitedBy | join(","))] | @tsv' -
Mitigate. Remove the stale target so that the source resolves, and add the guard (
cluster=~".+"insource_matchers, as in Artefact 2); reload withPOST /-/reloadorSIGHUP.[86] Do not addexternal_labels: {cluster: meta}to the meta-monitoring server: both alerts would carrycluster="meta", still equal, and the probe would stay muted. -
Verify.
amtool alert query --inhibitedno longer listsEndpointDown, and a testEndpointDownfrom the meta-monitoring server pages. -
Prevent. (a) Give
clusterone meaning, the affected cluster, and record the evaluating server inprometheus(Artefact 1). (b) Guard every inhibit rule: eachequallabel non-empty on the source. © Never let meta-monitoring alerts be inhibition targets (prometheus!="meta"). (d) Lint every rule, check every server’s external labels in CI, and track compliance (apromtooltest never seesexternal_labels). (e) Monthly, fire a test alert without the label from the meta-monitoring server and confirm that it pages.
Anti-patterns and myths
Link to section “Anti-patterns and myths”- “Buy AIOps to fix alert noise.” If rules page on causes, flap, or lack owners, a platform groups the noise more neatly. Fix the rules first (SRE).
- Reporting compression as success. Lab 2’s 5.5-times compression merged unrelated incidents.
- Suppression without expiry. Every permanent silence is a future missed incident.
- “The model will learn our topology.” Learned grouping learns only from the feedback its vendor counts (see governance); PagerDuty warns that test data can make it behave unpredictably.[27]
- Root-cause theatre. A confident single cause from a narrow menu can send responders the wrong way. Show the evidence and the runners-up.
- Autonomy first. Agents diagnose better than they resolve (Automation and AI). Start with suggestions; earn automation one action class at a time.
- Black-box vendor evaluation. A demo on the vendor’s data proves nothing about yours. Insist on shadow mode with your labels.
Deciding and adopting
Link to section “Deciding and adopting”When to use and when not to use
Link to section “When to use and when not to use”| Use AIOps techniques when | Do not use them yet when |
|---|---|
| One failure regularly produces many alerts across services or tools | Alert rules page on causes, flap, or have no owners: fix the rules first |
| Several monitoring tools page the same people with inconsistent alerts | You have one monitoring tool and a small estate whose topology people know |
| Seasonal metrics hide real faults from static thresholds | Nobody will label groupings and causes, so nothing can be measured |
| A recurring fault has a known, reversible fix that people apply by hand | The “fix” changes data, money or security posture: keep a person in the loop |
| Responders lose time reconstructing what changed and who owns what | Ownership and change records do not exist: build those first; they pay off on their own |
Hidden responsibilities. Someone must own the pipeline, keep topology current, run evaluations, review suppressions and approve automation classes; a managed platform hides that work rather than removing it.
Decision framework
Link to section “Decision framework”The technique tree decides what to adopt; this weighted worksheet chooses which platform or stack, after a shadow-mode trial on your labelled incidents. The weights are this Atlas’s suggestion; change them, but write down why.
| Criterion | Weight | How to score 1–5 | Evidence to ask for |
|---|---|---|---|
| Pairwise precision on your labelled incidents | 20 | 5 = meets your target in shadow mode | Their export of groups, scored with your labels |
| Pairwise recall and missed incidents | 20 | 5 = no missed incidents in the trial | Same |
| Explainability of each grouping and cause | 15 | 5 = every decision shows its evidence | Screenshots or API fields per decision |
| Integration with your monitors, ITSM and topology | 15 | 5 = native, two-way, no custom glue | A working connector in the trial |
| Portability (export alerts, groups, labels, rules) | 10 | 5 = full export through an API | API documentation |
| Safety of automation (allow-lists, throttles, approvals, audit) | 10 | 5 = all four, enforced | Configuration demonstrated live |
| Data handling (residency, retention, redaction) | 5 | 5 = meets policy without exceptions | Contract and documentation |
| Total cost over three years, including people | 5 | 5 = lowest of the options | Written quote plus internal effort estimate |
Maturity model (this Atlas’s model)
Link to section “Maturity model (this Atlas’s model)”This model is this Atlas’s proposal, not an industry standard. Move up only when the exit criteria hold for a full quarter.
| Level | Observable behaviour | Exit criteria | Typical constraint |
|---|---|---|---|
| 0. Raw alerts | Every monitor pages directly; duplicates are common | Alert inventory exists; noisiest rules known | No ownership data |
| 1. Hygiene | Label contract; deduplication; group_by; owners on every alert |
95% of alerts pass the contract (measured in Alertmanager); actionable-page rate measured | Inconsistent tools |
| 2. Context | Topology and change data attached to incidents; guarded inhibition | Labels captured at close for most incidents; first precision and recall scorecard | Topology freshness |
| 3. Measured intelligence | Learned or statistical grouping and anomaly detection run in shadow mode before release | Policies meet targets; missed incidents reviewed every time | Labelling effort |
| 4. Guarded automation | Allow-listed remediation for several fault classes; LLM summaries with human confirmation | Success and rollback rates within targets; no automation-caused incident in a quarter | Change-authority trust |
There is deliberately no level 5 “autonomous operations”: the evidence on this page does not support it as a goal for most organisations in 2026.
Adoption roadmap: 30/60/90 days
Link to section “Adoption roadmap: 30/60/90 days”| Window | Actions | Milestone | Metric |
|---|---|---|---|
| Days 1–30 | Name the event-intelligence owner. Export three months of alerts and incidents; measure alerts per incident, pages per week and the actionable-page rate. Write the label contract; lint every rule in CI; measure compliance weekly. Add one-click labels at close | Baseline report; contract in CI | Contract compliance; actionable-page rate |
| Days 31–60 | Deduplicate and group by cluster and service. Add two guarded inhibition rules. Build a topology file for tier-1 services, including shared infrastructure. Attach recent changes to incidents (Artefact 4). Start the monthly scorecard |
First scorecard | Pairwise precision and recall; split rate |
| Days 61–90 | Shadow-trial one statistical or learned technique (or one vendor) against the labels. Automate one reversible remediation class through the gate. Run a storm replay test | Go or no-go decision recorded | Shadow-mode scores; remediation success and rollback rates |
Quick wins usually come from the ten noisiest rules and from attaching changes to incidents; topology data is the usual blocker, so start collecting it on day 1.
Toolkit
Link to section “Toolkit”Checklists
Link to section “Checklists”Quick start (first week)
- An event-intelligence owner is named, and the time is in their objectives
- Three months of alerts and incidents exported; baseline alerts per incident and actionable-page rate
- The label contract (Artefact 1) is written
- Incident close asks “grouped correctly?” and “cause correct?”
Before enabling any suppression, inhibition or new grouping policy
- The policy is in version control, with checks (rule linting,
promtool test rules,amtool config routes test) - Every label in
equalnames the affected component (not the evaluating server) and is required non-empty insource_matchers - Alerts from meta-monitoring are excluded as inhibition targets
- Shadow-mode results on labelled incidents meet the precision, recall and missed-incident targets
- Suppressed alerts stay queryable; the suppression has an owner and an expiry date
- A rollback (revert and reload) has been rehearsed
Before automating a remediation class
- The fault is well understood, and the fix is reversible and idempotent
- Blast-radius limit, throttle and daily cap are set
- The runner’s credential can do this action and nothing else; the ingest endpoint is authenticated or bound to localhost
- Verification and rollback steps are automated; failure pages a person
- The change authority has approved the class; the review date is set
Monthly review
- Scorecard updated (Template 3), and every missed incident reviewed
- A person has inspected a random sample of inhibited and suppressed alerts, and the silences
- Topology entries older than 90 days re-confirmed by their owners
- The ten noisiest rules have actions assigned
Templates
Link to section “Templates”Template 1: policy record (one per grouping rule, inhibition, detector or remediation class)
Policy ID / name: e.g. INH-007 "ClusterUnreachable mutes symptoms"
Type: grouping | inhibition | suppression | detector |
remediation
Owner (team, person):
Scope: services, clusters, alertnames
Logic: link to the rule or config in version control (commit)
Labels relied on: each label in equal or group_by: its meaning
(affected or evaluating), who sets it, and the
non-empty guard
Evidence for release: shadow-mode period, labelled incidents used,
precision, recall, missed incidents
Failure mode if wrong: what could be hidden, merged or changed; e.g. INH-007:
the meta server loses its route to eu-1 while eu-1
still alerts, so eu-1's real alerts are muted
Expiry / review date:
Rollback: revert commit + reload, expected time
Approved by / date:
Template 2: automation safety review
Action class: e.g. rotate and compress logs on LogVolumeNearlyFull
Trigger (exact labels):
Allow-list entry: yes/no, and the commit
Blast-radius limit: max hosts per run / per hour; share of capacity
Throttle and daily cap: once_within ... ; max runs per day ...
Credential: identity, permissions, where stored, rotation
Verification: check that proves the fix worked, and timeout
Rollback: automatic step; who is paged on failure
Data, money or security impact: none / describe (if any, keep a person in the loop)
Change authority decision: approved / rejected, date, review date
Template 3: monthly evaluation scorecard
| Metric | Target | This month | Last month | Notes and actions |
|---|---|---|---|---|
| Pairwise precision (paging routes) | ||||
| Pairwise recall | ||||
| Over-merge rate | ||||
| Split rate | ||||
| Missed incidents (count, links to reviews) | 0 | |||
| Top-3 probable-cause accuracy | ||||
| Actionable page rate | ||||
| Remediation success / rollback / override | ||||
| Label-contract compliance |
Template 4: platform shadow-trial plan
Candidate and version:
Data supplied: N weeks of raw alerts, M labelled incidents (list),
topology file, change log
Mode: shadow only; no paging changes
Success criteria: precision >= __, recall >= __, missed incidents = 0,
an explanation shown for every group
Exports required: alerts, groups, causes, decisions with reasons (API)
Security and data review: residency, retention, redaction, sub-processors
Decision date and owner:
Deep comparisons
Link to section “Deep comparisons”Four traditions handle operational events; they are layers, not rivals.
| Approach | Unit of work | How it reduces noise | Strength | Weakness | Atlas page |
|---|---|---|---|---|---|
| ITIL event management | Informational, warning and exception events[87] | Filtering, categorising and correlating within a process | Ties events to incident, problem and change processes | Rules need constant upkeep | ITOps |
| SRE symptom-based alerting | SLOs and burn rates | Page only on user-visible symptoms | Few pages, high precision | Says what is broken, not why | SRE |
| AIOps and event intelligence | Groups of alerts as incidents | Deduplication, grouping, topology, learning | Works across tools and at scale | Needs labels and context; can be opaque | This page |
| Security analytics | Detections and cases | Tuning, ML-assisted triage | Built for an adversary | Base rates; evasion | AIOps for Security |
A sound design uses SLO alerting to decide what deserves a page, event management to connect events to processes, and AIOps to group, enrich and rank what remains.
Do we need data scientists? Not to start: levels 1 and 2 of the maturity model are engineering and ownership work. Evaluating detectors and vendors needs statistical literacy; data scientists only if you build models.
How many labelled incidents do we need? No credible published threshold exists. A few dozen expose gross over-merging; a fair comparison of learned grouping with rules needs more, across kinds of failure. The decision tree’s 100 is a rule of thumb.
Will AIOps reduce MTTR? It can shorten the time to engage the right team and find a probable cause, but overall MTTR measures that poorly: durations are skewed and the “R” is ambiguous (IncidentOps). Measure the phases AIOps affects.
Can an LLM do root-cause analysis for us? It can suggest causes for a person to confirm: Microsoft reported root-cause category accuracy up to 0.766 on its own incidents,[40] but agents rarely resolve live faults (see Automation and AI).
Should security alerts go through the same correlation engine? They can share plumbing, but evaluate and govern them separately: an attacker adapts to your detectors, and missed detections cost differently. See AIOps for Security.
Is Kubernetes self-healing AIOps? No. Restarting failed containers and rescheduling pods is the orchestrator’s built-in control loop (KubernetesOps). AIOps sits above it and correlates what such loops cannot fix.
Going further
Link to section “Going further”Advanced topics and emerging direction
Link to section “Advanced topics and emerging direction”| Topic | Status (October 2026) | What to watch |
|---|---|---|
| Graph-based and causal root-cause analysis | Active research; no method best in all situations;[48] vendor fault-tree analysis[24] | Results on real systems, not synthetic data |
| LLM summaries and diagnosis | Evaluated at Microsoft; one team’s production use (2023)[16][40] | Evaluation on your incidents; prompt injection; data handling |
| Agents that act (“AgentOps”, in AIOpsLab’s term) | Research and early products; low resolution rates in ITBench (early-2025 models); higher, differently defined diagnosis scores in 2026[19][20][61] | Whether gains in diagnosis carry over to live resolution; human approval gates |
| Shared semantic conventions | OpenTelemetry resource conventions (1.44.0) standardise service identity[68] | Fewer label mismatches between tools |
Distinguish three kinds of claim. Established: deduplication, grouping, inhibition, topology and change correlation, statistical baselines. Active research with limited production evidence: learned grouping, LLM summaries, LLM-assisted cause classification. Marketing and speculation: “autonomous operations”, single-number noise-reduction promises, root cause without evidence.
Learning path
Link to section “Learning path”- Prerequisites: alerting basics and SLOs (SRE), telemetry (ObservabilityOps), incident roles (IncidentOps), and a little Python and statistics (median, percentiles, precision and recall).
- One-day primer: the first three parts of this page; Google’s chapter on monitoring distributed systems;[10] Labs 2 and 3.
- One week: run Lab 1; write a label contract and lint your own rules; compute alerts per incident and the actionable-page rate for a month of alerts.
- Thirty days: label 20 incidents; score your current grouping with pairwise precision and recall; build a tier-1 topology file; attach changes to incidents.
- Advanced: study the surveys on AIOps failure management and LLM-era methods;[5][7][88] trial one learned technique in shadow mode; design a guarded remediation class end to end.
- Portfolio projects: (1) a storm-replay test harness for your alert pipeline; (2) an evaluation scorecard generated from incident labels; (3) a guarded remediation for one fault, with verification and rollback, reviewed by your change authority.
Wrap-up
Link to section “Wrap-up”Executive recap and cheat sheet
Link to section “Executive recap and cheat sheet”| Topic | Remember |
|---|---|
| What it is | Statistics, ML and LLMs on operational events: group, detect, rank, guard |
| What it is not | Observability, incident management, security analytics, or operations for AI |
| First moves | Label contract → deduplication → grouping and inhibition → topology and changes |
| When to add learning | Seasonal metrics, many inconsistent tools, enough labelled incidents to prove it in shadow mode |
| Metrics | Pairwise precision and recall, over-merge and split rates, missed incidents, top-k cause accuracy, remediation rates; compression only as context |
| Automation | Allow-listed, reversible, throttled, verified, least privilege; people approve new classes |
| LLMs | Read-only first; treat event text as untrusted; evaluate on your incidents |
| Tools | Alert routers, event-intelligence platforms, RCA built into observability suites, event-driven automation (tooling) |
| Watch-outs | Missing or two-meaning labels in inhibition, an open Alertmanager API, stale topology, holidays, slow drift, engine retirements |
| Next action | Measure your actionable-page rate and label 20 incidents this month |
A judgement call: buy a platform now, or fix alert hygiene first?
Link to section “A judgement call: buy a platform now, or fix alert hygiene first?”Situation (illustrative). A company runs three monitoring tools; on-call engineers receive about 1,500 pages a month, one in five actionable. Peak season starts in eight weeks. A vice-president proposes buying an event-intelligence platform now; a vendor demo claims a 90% reduction in noise.
Option A: buy now. Fast to approve, vendor help with integration, and cross-tool correlation is the platform’s strength. Option B: an eight-week hygiene sprint: a label contract, deduplication and grouping, retiring the noisiest rules, SLO-based paging for the top services and labels at incident close, then a shadow trial of one or two platforms after the peak.
Assumptions. Most of the noise comes from a few rules (it usually does, but check the export). The team can spare two engineers for eight weeks. No labelled incidents exist today.
Reasoning. Option A promises results without changing anyone’s habits, and can be wrong here for three reasons: without labels nobody can tell whether its grouping is right, so a wrong merge at peak could hide an incident; integration takes weeks, and the peak arrives regardless; and a demo on the vendor’s data says little about these three tools. Option B removes noise at source, creates the labels any later evaluation needs, and keeps risk low during the peak.
Decision. Choose B, and start collecting labels on day 1 so that the post-peak shadow trial has evidence. When A wins instead: if the noise comes from many tools whose alerts cannot be fixed at source (for example, appliances or third-party services), and the team has no capacity to run a composable stack, buy, but in shadow mode first, scored with the worksheet.
Uncertainty. The split between “fixable at source” and “only correlatable” noise is the crux. Measure it before deciding; a one-week analysis of the alert export settles most of the argument.
Learning objectives and mastery check
Link to section “Learning objectives and mastery check”After this page you should be able to: explain what AIOps covers and where its neighbours begin; select between rules, statistics, learned models and LLMs for a given noise problem; design a label contract, a topology file and a guarded remediation gate; operate an evaluation with pairwise precision and recall; and evaluate a vendor’s claims with your own labelled data.
1. Three alerts are grouped together. A1 and A2 belong to incident X, and B1 to incident Y. What are the pairwise precision and recall?
(A1, A2) are together and belong together: TP = 1. (A1, B1) and (A2, B1) are together but should not be: FP = 2. No pair that belongs together was split: FN = 0. Precision = 1 ÷ 3 ≈ 0.33; recall = 1 ÷ 1 = 1.0. The group found everything but mixed in an unrelated incident.
2. An inhibition rule uses equal: [cluster]. Neither the source alert nor a target alert has a cluster label. What happens, and how do you prevent it?
Alertmanager treats missing labels as equal empty values, so the target is muted. A constant external_labels value on the server
that raised both does not help: both get the same value. Prevent it by requiring the label non-empty on the source
(cluster=~".+" in source_matchers), letting cluster mean only the affected cluster (the evaluating server goes in another
label), excluding meta-monitoring alerts as targets, and firing a test alert without the label each month.
3. Your seasonal anomaly detector floods on public holidays. Name two fixes and one thing that will remain hard.
A holiday calendar mapping those days to a weekend-like baseline (in Lab 3 it removed all 32 holiday false alerts, leaving 2 from a campaign), and change or campaign feeds that explain planned events. Slow drifts remain hard because the baseline absorbs them; keep SLO burn-rate alerts as an independent net.
4. Which faults qualify for automatic remediation?
Well-understood faults with a reversible, idempotent fix, a limited blast radius, an automated check that proves success, and an automatic rollback or page. The runner acts with the narrowest identity, and the change authority approves the class. Anything touching data, money or security posture keeps a person in the loop.
5. A vendor demo shows a 95% reduction in noise. What do you ask for before believing it?
A shadow-mode run on your alerts, scored with your labels (pairwise precision and recall, over-merge and split rates, missed incidents), an explanation of each decision, a full export, and their limits under a storm.
6. Where does this page end and AIOps for Security begin?
The techniques overlap, but AIOps handles faults, which do not adapt to the detector; security analytics faces an adversary who does, which changes evaluation (base rates, evasion, missed detections) and safe autonomy. That is an editorial boundary of this Atlas.
Conclusion
Link to section “Conclusion”AIOps is best understood as a measurement discipline sold as a product category. Its techniques, from deduplication to language models, are real and useful, and each can also hide an outage. The name does not tell you which outcome you will get, and that is why this page keeps returning to labelled incidents.
The durable assets are not the engine. They are the label contract, the topology, the change log, the labelled incidents and the habit of scoring every policy before and after it ships. Organisations that build those can swap engines as vendors merge, rename or retire products, and can tell whether a new technique helps. Organisations that skip them buy a cleaner-looking alert stream and learn its precision from their customers.
Sources and further reading
Link to section “Sources and further reading”Claim-by-claim notes, support strength and the sources that could not be
fetched are in the evidence ledger (research/aiops-ledger.md). Analyst reports are paywalled; only text quoted by vendors is used,
attributed as such.
Re-checking fast-moving facts (all as of October 2026). Monthly: the ITBench-AA leaderboard. Quarterly: pinned versions
(Alertmanager, Prometheus, pint, ansible-rulebook, the ansible.eda collection, the node_exporter mixin, Keep, OpenTelemetry),
vendor packaging and limits (PagerDuty’s AIOps add-on, BigPanda’s 300-alert cap), retirement or archive notices (DevOps Guru,
Merlion) and NIST’s AI RMF revision. Whenever the AI Act is amended: its dates, on EUR-Lex or the AI Act Explorer. The Gartner
glossary refuses automated access, so re-check it through a new Internet Archive snapshot. Update the footnote date and ledger
row at each re-check.
Term, analysts and history
Practice and reliability engineering
Alerting, labels and configuration
Products and projects (time-sensitive)
Methods and statistics
Language models and agents
Governance
Further reading
- Google, Site Reliability Engineering and The Site Reliability Workbook: the alerting and automation chapters are the best antidote to over-engineered event pipelines.
Changelog
- 2026-10-16: first version (research, ledger, labs executed, diagrams validated) by the managing author; awaiting independent fact-check review.
- 2026-10-17: round-1 revision (
reviews/aiops-r1.md, response inreviews/aiops-r1-response.md): affected cluster separated from evaluating server; guarded inhibition and corrected runbook fix; contract linting and measurement; remediation wired end to end; ITBench (ICML 2025) and a dated 2026 leaderboard; predictive alerting; Alertmanager API security; EU AI Act Article 4 and Digital Omnibus; labs re-run; one redundant figure removed. - 2026-10-17: round-2 revision (
reviews/aiops-score.md, response inreviews/aiops-r2-response.md): how log templates, learned grouping and graph root-cause analysis work, with sceptical evidence; re-check guidance; runner after routing in the architecture figure; both mixin remedies; observer-side partition risk; code wrapped; repetition cut; labs re-run. - 2026-10-17, post-score polish (
reviews/aiops-score-r2.md; actions inreviews/aiops-polish.md): change events recorded and attached (Artefact 4, executed); Landauer finding made precise; Forrester figures attributed; NIST AI RMF revision noted; moving-branch sources pinned; re-check list extended; repetition cut.
Definition of AIOps (Artificial Intelligence for IT Operations) — Gartner IT Glossary, Internet Archive snapshot of 2026-02-14. Checked 2026-10-16. ↩︎ ↩︎
Applying AIOps Platforms to Broader Datasets Will Create Unique Business Insights — Colin Fletcher, Gartner, published 2016-07-01 (public summary, archived 2025-01-26). Checked 2026-10-16. ↩︎ ↩︎
Dynatrace Named a Leader in AIOps in Report by a Leading Independent Research Firm — Dynatrace press release on The Forrester Wave: AIOps Platforms, Q2 2025, 2025-04-15. Checked 2026-10-17. ↩︎ ↩︎
AIOps: Real-World Challenges and Research Innovations — Yingnong Dang, Qingwei Lin, Peng Huang, ICSE 2019 Technical Briefings, Microsoft Research, 2019. Checked 2026-10-16. ↩︎ ↩︎
A Systematic Mapping Study in AIOps — Paolo Notaro, Jorge Cardoso, Michael Gerndt, arXiv:2012.09108 (AIOPS 2020 workshop), 2020-12-15. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Key Takeaways From the 2025 Gartner Market Guide for Event Intelligence Solutions — Dallon Robinette, Selector, 2026-02-06. Checked 2026-10-16. ↩︎ ↩︎
AIOps Solutions for Incident Management: Technical Guidelines and A Comprehensive Literature Review — Youcef Remil, Anes Bendimerad, Romain Mathonat, Mehdi Kaytoue, arXiv:2404.01363, 2024-04-01. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Alertmanager — Prometheus documentation. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Understanding and Handling Alert Storm for Online Service Systems — Nengwen Zhao et al., ICSE 2020 (Software Engineering in Practice). Checked 2026-10-16. ↩︎ ↩︎ ↩︎
Monitoring Distributed Systems — Rob Ewaschuk, in Site Reliability Engineering, Google / O’Reilly, 2016. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Observability Survey Report 2026 — Grafana Labs (1,363 self-selected responses via Censuswide), 2026. Checked 2026-10-16. ↩︎
Watchdog RCA — Datadog documentation, modified 2026-08-06. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Introduction to Tivoli Netcool/OMNIbus — IBM Documentation, Netcool/OMNIbus 8.1.0. Checked 2026-10-16. ↩︎
Artificial Intelligence for IT Operations (AIOPS) Workshop White Paper — Jasmin Bogatinovski et al., arXiv:2101.06054, 2021-01. Checked 2026-10-16. ↩︎
Towards intelligent incident management: why we need it and how we make it — Zhuangbin Chen et al., ESEC/FSE, Microsoft Research, 2020-11. Checked 2026-10-16. ↩︎ ↩︎
Recommending Root-Cause and Mitigation Steps for Cloud Incidents using Large Language Models — Toufique Ahmed et al., ICSE 2023, arXiv:2301.03797. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Dell Technologies acquires Moogsoft — Phil Tee, Moogsoft, 2023-10-19. Checked 2026-10-16. ↩︎ ↩︎
Elastic and Keep join forces to help users manage alerts and automate workflows — Ken Exner, Elastic, 2025-05-07. Checked 2026-10-16. ↩︎ ↩︎
AIOpsLab: A Holistic Framework to Evaluate AI Agents for Enabling Autonomous Clouds — Yinfang Chen et al., arXiv:2501.06706, 2025-01. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
ITBench: Evaluating AI Agents across Diverse Real-World IT Automation Tasks — Saurabh Jha et al., ICML 2025 spotlight poster (preprint v1, arXiv:2502.05352: 94 scenarios, 13.8%). Checked 2026-10-16. ↩︎ ↩︎ ↩︎
Gartner Market Guide for Event Intelligence Solutions — PagerDuty report page (citation: Martin Caren, Andre Bridges, Leo Li, 5 May 2026). Checked 2026-10-16. ↩︎
Gartner Market Guide for Event Intelligence Solutions, 2026 — BigPanda report page quoting Gartner’s definition, 2026. Checked 2026-10-16. ↩︎
Alerting on SLOs — The Site Reliability Workbook, Google / O’Reilly, 2018. Checked 2026-10-16. ↩︎ ↩︎
Root cause analysis concepts — Dynatrace documentation, updated 2026-10-12. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Unit testing for rules — Prometheus documentation. Checked 2026-10-16. ↩︎ ↩︎
Alertmanager README (amtool) — Prometheus project, v0.34.1. Checked 2026-10-16. ↩︎ ↩︎
Intelligent Alert Grouping — PagerDuty Knowledge Base, updated 2026-09. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Security model — Prometheus documentation (Alertmanager section). Checked 2026-10-16. ↩︎ ↩︎
Alertmanager configuration — Prometheus documentation. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Introduction — Benjamin Treynor Sloss, in Site Reliability Engineering, Google / O’Reilly, 2016. Checked 2026-10-16. ↩︎
Content-Based Alert Grouping — PagerDuty Knowledge Base, updated 2026-09. Checked 2026-10-16. ↩︎ ↩︎
Alert Correlation Logic — BigPanda documentation. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
Detection of Outliers (1.3.5.17) — NIST/SEMATECH e-Handbook of Statistical Methods. Checked 2026-10-16. ↩︎ ↩︎
STL decomposition (§3.6) — Rob J. Hyndman and George Athanasopoulos, Forecasting: Principles and Practice, 3rd ed., OTexts. Checked 2026-10-16. ↩︎
promql-anomaly-detection — Grafana Labs on GitHub, README. Checked 2026-10-16. ↩︎ ↩︎
Query functions — Prometheus documentation (
predict_linear). Checked 2026-10-16. ↩︎ ↩︎node-mixin config.libsonnet — Prometheus node_exporter project, v1.12.1 of 2026-07-14 (the rule is in
alerts/alerts.libsonnet). Checked 2026-10-17. ↩︎ ↩︎ ↩︎Novelty and outlier detection — scikit-learn user guide. Checked 2026-10-16. ↩︎ ↩︎
AIOps Labs — Elastic documentation. Checked 2026-10-16. ↩︎ ↩︎
Automatic Root Cause Analysis via Large Language Models for Cloud Incidents — Yinfang Chen et al., arXiv:2305.15778 (v4, 2023-11-13; deployment in §1 and §5.5 of the full text). Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Drain3 — logpai on GitHub, README (online template miner after Drain, ICWS 2017). Checked 2026-10-17. ↩︎ ↩︎
Experience Report: System Log Analysis for Anomaly Detection — Shilin He, Jieming Zhu, Pinjia He, Michael R. Lyu, ISSRE 2016. Checked 2026-10-17. ↩︎
A Critical Review of Common Log Data Sets Used for Evaluation of Sequence-based Anomaly Detection Techniques — Max Landauer, Florian Skopik, Markus Wurzenberger, FSE 2024 (§IV-C). Checked 2026-10-17. ↩︎ ↩︎
Log-based Anomaly Detection with Deep Learning: How Far Are We? — Van-Hoang Le, Hongyu Zhang, ICSE 2022. Checked 2026-10-17. ↩︎
Group similar events with Smart Mode in ITSI — Splunk IT Service Intelligence documentation. Checked 2026-10-17. ↩︎
Time-based Clustering with Tempus — Moogsoft Onprem/Hosted documentation, v9. Checked 2026-10-17. ↩︎
PyRCA: A Library for Metric-based Root Cause Analysis — Chenghao Liu et al., Salesforce, arXiv:2306.11417, 2023 (code: https://github.com/salesforce/PyRCA). Checked 2026-10-17. ↩︎ ↩︎
Root Cause Analysis for Microservice System based on Causal Inference: How Far Are We? — Luan Pham, Huong Ha, Hongyu Zhang, ASE 2024. Checked 2026-10-17. ↩︎ ↩︎
Alertmanager release 0.34.1 — Prometheus project on GitHub, 2026-09-17. Checked 2026-10-16. ↩︎ ↩︎
keephq/keep — Keep on GitHub (release v0.54.3 of 2026-09-09). Checked 2026-10-16. ↩︎
Auto-Pause Incident Notifications — PagerDuty Knowledge Base. Checked 2026-10-16. ↩︎
Event Orchestration — PagerDuty Knowledge Base. Checked 2026-10-16. ↩︎
IT Operations Needs a New Wardrobe — Dell Technologies blog, 2024-05-20. Checked 2026-10-16. ↩︎
Overview of Event Analytics in ITSI — Splunk IT Service Intelligence documentation. Checked 2026-10-16. ↩︎
Rules — Ansible Rulebook documentation — Red Hat / Ansible community, v1.3.0 (latest release 1.3.2: https://github.com/ansible/ansible-rulebook/releases/tag/v1.3.2). Checked 2026-10-16. ↩︎ ↩︎
Merlion — Salesforce on GitHub (archived 2026-03-11). Checked 2026-10-16. ↩︎ ↩︎
Transitioning off Amazon Lookout for Metrics — AWS Machine Learning Blog, 2024-10-09. Checked 2026-10-16. ↩︎
What is Anomaly Detector? — Microsoft Learn (previous versions), updated 2025-06-12. Checked 2026-10-16. ↩︎
What is Amazon DevOps Guru? — AWS documentation (end-of-support notice). Checked 2026-10-16. ↩︎
AlertGuardian: Intelligent Alert Life-Cycle Management for Large-scale Cloud Systems — Guangba Yu et al., ASE 2025, arXiv:2601.14912, 2026-01-21. Checked 2026-10-16. ↩︎
ITBench-AA Benchmark Leaderboard — Artificial Analysis (undated page, © 2026). Checked 2026-10-16. ↩︎ ↩︎
Prometheus release 3.15.0 — Prometheus project on GitHub, 2026-09-24. Checked 2026-10-16. ↩︎
cmd/pint/lint.go — pint v0.89.2 source (released 2026-10-08;
--fail-ondefaults tobug). Checked 2026-10-17. ↩︎ ↩︎Alerting rules — Prometheus documentation. Checked 2026-10-16. ↩︎ ↩︎
Configuration — Prometheus documentation (
external_labels). Checked 2026-10-16. ↩︎rule/label — pint documentation, Cloudflare. Checked 2026-10-16. ↩︎
Changelog — pint documentation (v0.72.0 entry). Checked 2026-10-16. ↩︎
Service semantic conventions — OpenTelemetry, semantic conventions 1.44.0. Checked 2026-10-16. ↩︎ ↩︎
Conditions — Ansible Rulebook documentation — Red Hat / Ansible community, v1.3.0. Checked 2026-10-16. ↩︎
Rulebooks — Ansible Rulebook documentation, v1.3.0 (
execution_strategy, default sequential). Checked 2026-10-17. ↩︎alertmanager.py event source plugin — ansible/event-driven-ansible on GitHub, collection v2.13.0 of 2026-07-07. Checked 2026-10-17. ↩︎
webhook.py event source plugin — ansible/event-driven-ansible on GitHub, collection v2.13.0 of 2026-07-07. Checked 2026-10-17. ↩︎
Limiting hosts — Ansible Rulebook documentation, v1.3.0. Checked 2026-10-17. ↩︎
Understanding privilege escalation: become — Ansible Community Documentation. Checked 2026-10-17. ↩︎
The Evolution of Automation at Google — Site Reliability Engineering, Google / O’Reilly, 2016. Checked 2026-10-16. ↩︎
cli/alert_query.go — Alertmanager source, v0.34.1 (flags of
amtool alert query;amtool alert addis incli/alert_add.go). Checked 2026-10-16. ↩︎ ↩︎ ↩︎Evaluation of clustering — Christopher D. Manning, Prabhakar Raghavan, Hinrich Schütze, Introduction to Information Retrieval, Cambridge University Press, 2008. Checked 2026-10-16. ↩︎ ↩︎
Classification: Accuracy, recall, precision, and related metrics — Google Machine Learning Crash Course. Checked 2026-10-16. ↩︎ ↩︎
HTTPS and authentication — Prometheus documentation for Alertmanager (“experimental”). Checked 2026-10-16. ↩︎
Article 4: AI literacy — EU AI Act as amended, AI Act Explorer. Checked 2026-10-16. ↩︎
Digital Omnibus on AI — Regulation (EU) 2026/1744 of 8 July 2026, official text as reproduced in the AI Act Explorer (in force 2026-07-27). Checked 2026-10-17. ↩︎ ↩︎
Annex III: High-Risk AI Systems Referred to in Article 6(2) — EU AI Act text as published by the Future of Life Institute’s AI Act Explorer. Checked 2026-10-17. ↩︎
AI Risk Management Framework — National Institute of Standards and Technology, living page (AI RMF 1.0 of 2023-01-26). Checked 2026-10-17. ↩︎
Alertmanager API v2 OpenAPI specification — Prometheus project, v0.34.1. Checked 2026-10-16. ↩︎
inhibit.go — Alertmanager source, v0.34.1 (
inhibitedByholds the inhibiting alerts’ fingerprints). Checked 2026-10-16. ↩︎Alertmanager management API — Prometheus documentation. Checked 2026-10-16. ↩︎
IT Event Management Explained — Splunk (summary of ITIL 4 event categories), undated. Checked 2026-10-16. ↩︎
A Survey of AIOps for Failure Management in the Era of Large Language Models — Lingzhe Zhang et al., arXiv:2406.11213 (v4), 2024-06. Checked 2026-10-16. ↩︎