Change-Driven Alert Suppression in EMS ΒΆ
Design Document Β· EMS Platform Team
π Draft Β |Β π― Scope: PCC Team Alert Triage Β |Β π EMS + EAP Change Agent
Contents ΒΆ
- Background
- System Architecture Overview
- Problem Statement
- Solution Design
- Scope
- Decision Rationale
- Flow Diagram
- EMS Required Changes
- Operator Workflow Change
- Success Metrics
1. Background ΒΆ
During planned maintenance changes (ServiceNow Change Requests), related alerts flood the EMS feed, causing noise for the PCC team. Today there is no automated mechanism to suppress these expected alerts for the duration of the change window.
2. System Architecture Overview ΒΆ
βββββββββββββββββββββββββββββββββββ βββββββ ββββββββββββββββββββββ
β ALERT SOURCES β β β β USERS β
β Grafana / Prometheus AlertMgr β β β β PCC Team β
β Splunk β βββ β EMS β βββ β Service Ops Teams β
β TAP Tests β β β β (Alert triage) β
β EM7 β β β ββββββββββββββββββββββ
β ThousandEyes β βββββββ
β SolarWinds β
βββββββββββββββββββββββββββββββββββ
3. Problem Statement ΒΆ
When a service owner executes a planned change (e.g. a network or infrastructure maintenance), a burst of expected alerts is generated by the upstream monitoring systems and lands in the EMS feed. Triage owners must manually distinguish these expected change-related alerts from genuine incidents, increasing triage time and cognitive load.
There is currently no automated suppression tied to the change lifecycle. The desired behaviour is: when a ServiceNow change enters Scheduled status, the alerts that are predictably caused by that change are automatically suppressed in EMS for the duration of the change window.
4. Solution Design ΒΆ
4.1 Trigger ΒΆ
EMS subscribes to all ServiceNow change-status events as the single source of truth for suppression triggers β regardless of whether the status was updated via EAP or directly in ServiceNow. When a change transitions to Scheduled, EMS directly creates a Maintenance Window in code. No external post-step call is needed.
4.2 Maintenance Window Creation ΒΆ
When the Scheduled event is received, EMS creates a Maintenance Window with two components:
- CEL expression β built from the change's affected CI / customer fields.
- Phase 1: static rule-based build directly from change metadata (e.g.
customer == 'Acme Corp',labels.device_name == 'web-server-01'). The CI list in the ticket is expected to already be comprehensive at this point (see note below). - Phase 2 (future): an AI Agent builds the CEL expression from broader change context, enabling richer and more accurate scope inference.
- Phase 1: static rule-based build directly from change metadata (e.g.
- Window schedule β
start_timeandend_timeare set from the change's planned start and end dates.
4.3 Alert Suppression Behaviour ΒΆ
Upstream: CI coverage at ticket creation time
Topology-based CI expansion (discovering VMs running on an affected host, peer/cluster members not explicitly listed, etc.) should happen when the change ticket is being created, not at suppression time. The affected CI list in ServiceNow should already be complete and accurate by the time the ticket reaches Scheduled status.
While the Maintenance Window is active, any incoming alert whose fields match the CEL expression is marked with status = SUPPRESSED in EMS. Suppressed alerts remain visible in the feed but filterable, and an audit trail entry is written (change ticket label in alert body). Same change ticket alerts can be grouped together for easy triage. Alerts that do not match are processed normally.
4.4 Early Window Termination ΒΆ
When an operator sets a change to Complete, Cancel, or Review in ServiceNow before its scheduled end time, EMS detects the status-change event via the same subscription and deactivates the corresponding Maintenance Window by setting end_time = now(). All subsequent alerts then resume normal processing.
4.5 Phase 2 β AI-assisted CEL Build ΒΆ
In Phase 2, the static CEL build step is replaced by an AI Agent that derives the CEL expression from broader change context (ticket description, CMDB relationships, historical patterns, etc.). This enables more accurate and comprehensive suppression scope without requiring operators to manually maintain an exhaustive affected-CI list. Phase 2 is out of scope for the current implementation.
5. Scope ΒΆ
In scope
This suppression mechanism serves the PCC team alert triage workflow in EMS. It suppresses alerts within the EMS feed for the duration of a planned change window.
Out of scope
- Suppression in Control Hub or any other downstream alert consumer. Each system's suppression remains that system's own responsibility.
- A unified / cross-team "enterprise suppression platform." This design deliberately solves the current PCC pain point without trying to build a big, all-encompassing solution that would take significantly longer to deliver and get buy-in for.
6. Decision Rationale ΒΆ
Why not suppress upstream (Grafana / Splunk)? ΒΆ
Silencing rules in Grafana AlertManager or Splunk requires per-rule action, with no centralised view of what is silenced and why. Mapping a change's affected devices to the correct Grafana/Splunk alert rules is operationally fragile and does not scale as the number of rules and changes grows. It also leaves the noise problem unsolved for any additional alert sources that onboard to EMS in the future.
Why not add a dedicated filter/relay layer between upstream and EMS? ΒΆ
Inserting a new filtering layer (similar to an "AlertHub") would likely face objection from the LMA team, who own the upstream pipeline. It would also introduce a new service to maintain, increase end-to-end latency, and create a dependency on a separate component that is outside the EMS team's operational boundary.
Why EMS Maintenance Windows? ΒΆ
EMS already has a Maintenance Window feature (backed by CEL evaluation per incoming alert) that is purpose-built for exactly this use case. Hooking the Change Agent into it requires only the changes listed in Β§8, keeps all suppression logic within EMS where the PCC team already operates, and avoids introducing any new service or cross-team dependency.
7. Flow Diagram ΒΆ
flowchart TD
%% ββ Upstream: change creation via EAP (separate flow) ββββββββββββββββ
subgraph CREATION ["π§ Change Creation (via EAP Change Agent)"]
direction TB
CREATE_USER(["π€ Operator creates
Change Ticket in EAP"])
TOPO_AGENT["AI Agent queries
CI / Device Topology"]
TOPO_VMS["Discover: VMs / workloads
running on affected host"]
TOPO_PEERS["Discover: peer / cluster members
not explicitly listed"]
FILL_CI["Populate Affected CI list
in ServiceNow ticket"]
CREATE_USER --> TOPO_AGENT
TOPO_AGENT --> TOPO_VMS
TOPO_AGENT --> TOPO_PEERS
TOPO_VMS --> FILL_CI
TOPO_PEERS --> FILL_CI
end
%% ββ Main suppression flow ββββββββββββββββββββββββββββββββββββββββββββ
SN_USER(["π€ Operator sets Change to
'Scheduled' in ServiceNow"])
EMS_SUB["EMS subscribes to all
ServiceNow change-status events
(single source of truth)"]
SN_USER -- "ServiceNow\nstatus event" --> EMS_SUB
EMS_SUB --> MW_CREATE["Create Maintenance Window
in EMS"]
subgraph PHASE2["β‘ Phase 2 β AI-assisted CEL Build"]
direction TB
AI_CEL_BUILD["AI Agent
builds CEL expression
from change context"]
end
MW_CREATE -- "Phase 2\n(AI-assisted)" --> AI_CEL_BUILD
subgraph PHASE1["Phase 1 β Static CEL Build"]
direction TB
CEL_BUILD["Build CEL Expression
from Change Metadata"]
CEL_CUST["Customer filter
e.g. customer == 'Acme Corp'"]
CEL_CI["Affected CI filter
e.g. labels.device_name == 'web-server-01'"]
CEL_BUILD --> CEL_CUST
CEL_BUILD --> CEL_CI
end
MW_CREATE -- "Phase 1\n(static rules)" --> CEL_BUILD
MW_CREATE --> SCHED["Set Window Schedule
from Change Schedule"]
SCHED --> SCHED_OUT["start_time: change.scheduled_start
end_time: change.scheduled_end"]
AI_CEL_BUILD --> MW_ACTIVE
CEL_CUST --> MW_ACTIVE
CEL_CI --> MW_ACTIVE
SCHED_OUT --> MW_ACTIVE
MW_ACTIVE{{"Maintenance Window
Active in EMS"}}
MW_ACTIVE --> MATCH{"Incoming alert
matches window CEL?"}
MATCH -- No --> NORMAL["Alert processed normally
(stored, triaged, etc.)"]
MATCH -- Yes --> SUPPRESSED["Alert enters EMS
with status = SUPPRESSED
+ change_number label injected
β Visible in feed
β Audit trail written"]
%% ββ Early termination ββββββββββββββββββββββββββββββββββββββββββββββββ
CLOSE_USER(["π€ Operator sets Change to
'Complete / Cancel / Review'
in ServiceNow"])
CLOSE_EMS["EMS subscription detects
status change event"]
CLOSE_ACTION["Deactivate Maintenance Window
set end_time = now()"]
CLOSE_USER -- "ServiceNow\nstatus event" --> CLOSE_EMS
CLOSE_EMS --> CLOSE_ACTION
CLOSE_ACTION --> MW_END(["Window terminated early
Alerts resume normal processing"])
8. EMS Required Changes ΒΆ
| # | Change | Description | Priority |
|---|---|---|---|
| 1 | Subscribe to ServiceNow change-status events | EMS subscribes to ServiceNow change-status events as the single source of truth for all suppression triggers. On detecting a transition to Scheduled, EMS directly creates the corresponding Maintenance Window in code β no external post-step call is required. The same subscription also drives early termination: when a change transitions to Complete / Cancel / Review, EMS automatically deactivates the Maintenance Window by setting end_time = now(). | P1 |
| 2 | Change-to-CEL translation logic | EMS must be able to parse a ServiceNow change record and derive a valid CEL expression for the Maintenance Window. Phase 1: rule-based extraction β map the change's customer field to a customer == clause and each entry in the affected CI list to a labels.device_name == clause, combined with \|\|. Phase 2 (future): delegate CEL construction to an AI Agent that reads the full change context to produce a richer, more accurate expression. Also covers modifying the Maintenance Window on early termination. | P1 |
| 3 | Add change_number label to alert body | When an alert is suppressed by a Maintenance Window created from a ServiceNow change, inject the change number (e.g. CHG0012345) as a label into the alert enrichment. This enables: building a Change preset in EMS, querying suppressed alerts by change number for post-change review, and driving per-change suppression metrics (see Β§10). | P1 |
9. Operator Workflow Change ΒΆ
Before (today) ΒΆ
Operators manually add a ticket_number=CHGxxxx label to alerts they believe are change-related, then manually group those alerts into a Group Alert.
After (with this solution) ΒΆ
EMS auto-injects the change_number label on suppressed alerts and automatically groups them under the corresponding change's Group Alert. Operators no longer need to do this manually for alerts within scope.
Suppressed alerts will not appear in operators' default view, reducing noise and cognitive load during triage.
Manual fallback for missed alerts ΒΆ
When an operator identifies an alert that was not automatically suppressed but is clearly change-related, they can:
- Manually add the
change_number=CHGxxxxlabel to the alert. - Batch-update the alert status to Suppressed.
- Add the alert to the corresponding change Group Alert.
Why this matters ΒΆ
Every manually tagged alert is a signal that the auto-suppression scope missed something. Aggregating manual and automatic suppressions together lets the team:
- Identify coverage gaps and iterate on CEL rules β or generate AI skills to close them.
- Measure total suppression volume (auto + manual) and the auto hit rate.
- Quantify ops effort saved, building the business case for continued investment.
10. Success Metrics ΒΆ
All metrics below are derivable from the change_number label automatically injected on suppressed alerts (Β§8.3) plus the manual-fallback tagging described in Β§9.
Ops Effort Saved ΒΆ
- Estimated triage hours eliminated β suppressed alert count Γ average time an operator would spend triaging a change-related alert. This is the headline ROI figure to present to stakeholders.
- Manual labeling toil removed β volume of alerts that would previously have required a human to add
ticket_number=CHGxxxxand group manually, now handled automatically.
CEL Coverage Accuracy ΒΆ
- Auto-suppression coverage rate β auto-suppressed alerts Γ· (auto-suppressed + manually-tagged missed alerts). Tracks how well the CEL rules capture the actual change scope. A declining rate signals rule drift; a persistently low rate for a change type justifies building a Phase 2 AI skill for that category.
Team Performance During Change Windows ΒΆ
- MTTA / MTTR for genuine incidents β mean time to acknowledge and resolve alerts that are not change-related, measured during active change windows before vs. after suppression is enabled. Fewer distractions from noise should produce a measurable drop.
- Change noise ratio β change-related alerts as a percentage of all alerts fired during a window. Quantifies the scale of the problem and the magnitude of improvement.
Auditability & Compliance ΒΆ
- Post-change review completeness β after a change closes, every alert suppressed during the window is queryable by change number. Supports CAB reviews, SLA reporting, and incident retrospectives without manual reconstruction.
Implementation note
Add
change_numberas a filterable label in EMS. The existing facet / preset system can then expose a Change preset automatically once the label is present.