Skip to content
返回运维与 SRE

告警疲劳

降低告警量使每个 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 告警带受害者列表)以压噪声而不丢信号。
  • ✓每服务给月告警预算;超出强制审查,使疲劳成被测被拥有问题而非感觉。