告警疲劳
降低告警量使每个 page 有意义 — 修剪、聚合和噪声预算。
为什么
当工程师一班 40 个 page,他们停止仔细读 — 确认、瞥一眼、假设又一个误报。这正是真实 SEV1 被忽略 30 分钟的心理状态,因为它埋在低信号 page 流中训练工程师把所有告警当噪声。告警疲劳不是烦扰;它是延长宕机的直接原因。修法是无情修剪:每个无用户可见行动就触发的告警要么删要么转工单,目标是 <5 page/值班班。跟踪"每班 page 数"并 修剪到此目标的团队快抓真实宕机因为每个 page 被认真对待。
何时使用
当每值班班 page 超过 5,或工程师承认确认而不读时。月度审查。
如何做
1. 测基线 - 过去 30 天"每班 page 数",按团队和服务 - "行动率" = 导致真实行动的 page / 总 page - 若行动率 <70%,你有疲劳 2. 分类过去 30 天每个触发告警 - 行动:导致调查/修复 → 保留 - 噪声:触发但预期(部署、已知抖动)→ 静音或加 'for' 窗口 - 冗余:另一告警的重复 → 聚合或删 - 无 runbook:没人知怎么做 → 写 runbook 或删 3. 按类施修 - 噪声:加更长 'for' 窗口,或部署窗口静音 - 冗余:聚合(如"5 服务挂"→ 1 告警非 5) - 无 runbook:30 分钟内写不出 runbook 则删 - 目标:<5 page/班,>90% 行动率 4. 加噪声预算 - 每服务月"告警预算"(如 10 page/月) - 超出触发强制团队告警审查 - 这使疲劳成被测被拥有的问题,非感觉 5. 使修剪成循环仪式 - 团队复盘月度告警审查:"什么触发了、我们做了什么、删什么" - 删是默认;保留告警需理由
示例
# 告警审计脚本 — 分类过去 30 天 page
# 输出:每告警行动率、删除候选
import json
pages = json.load(open('pagerduty-export-30d.json'))
by_alert = {}
for p in pages:
by_alert.setdefault(p['alert_name'], []).append(p)
print(f"{'告警':40} {'次数':>5} {'行动':>5} {'率':>5}")
for name, ps in sorted(by_alert.items(), key=lambda x: -len(x[1])):
acted = sum(1 for p in ps if p.get('action_taken'))
rate = acted / len(ps)
flag = "删除?" if rate < 0.5 else ""
print(f"{name:40} {len(ps):>5} {acted:>5} {rate:>5.0%} {flag}")
# 样本输出:
# HighCPU 42 8 19% 删除?
# CheckoutSLOBurnRateFast 3 3 100%
# DiskSpaceLow 18 2 11% 删除? (自恢复)
# DBConnectionFailed 7 7 100%
# 行动:删 HighCPU + DiskSpaceLow → page/班从 12 降到 4常见问题
- ⚠把告警修剪当一次性清理而非月度仪式 — 每新功能加告警,疲劳一季内回归。
- ⚠因"也许某天需要"保留告警 — 永不触发的告警免费,触发无行动的告警贵;无情删。
- ⚠不测每班 page 数或行动率 — 无数字疲劳是感觉,团队无法向管理论证修剪工作。
- ⚠什么都不聚合 — 5 服务挂触发 5 page;一条聚合告警带受害者列表是一 page 且远不疲劳。
最佳实践
- ✓把每班 page 数和行动率作 KPI 跟踪;目标 <5 page/班且 >90% 行动率,月度团队复盘审查。
- ✓使删除为默认保留为例外 — 告警留下仅当有人用 runbook 和用户影响故事论证它。
- ✓聚合相关告警(5 服务挂 → 1 告警带受害者列表)以压噪声而不丢信号。
- ✓每服务给月告警预算;超出强制审查,使疲劳成被测被拥有问题而非感觉。