📑 本页目录(点开跳转)
08 · 告警为什么没人看
⏱ 42 分钟 | 🎁 短,但能救你很多个夜晚
🎯 一句话
一个每天响 20 次的告警,和没有告警是一样的 —— 甚至更糟, 因为它让你以为自己有监控。
📉 一、告警疲劳是怎么发生的
对照
第 1 周:加了 30 个告警,感觉很安心
第 2 周:每天响 15 次,大部分是正常波动
第 3 周:开始有人说「这个不用管」
第 4 周:建了个专门的群,把告警都扔进去
第 8 周:那个群没人看了
第 12 周:真的出事了,告警响了,【没人看见】 💀
🔑 关键的数字:如果一个告警的误报率超过 50%,它在心理上就已经失效了。 人不会持续响应一个「多半是假的」的信号 —— 这不是态度问题,是必然。
🎚️ 二、告警分级:不是所有异常都该叫醒你
对照
P0 立刻处理(打电话叫醒)
· 服务不可用、错误率暴涨
· 直接影响钱的(支付失败率、下单失败率)
⭐ 判据:多等 1 小时会造成不可逆损失
P1 当天处理(工作时间推送)
· 模型指标明显下滑、降级持续触发
· 关键特征缺失率飙升
P2 本周看(进日报,不推送)⭐
· 分布轻微漂移、长尾指标波动
· 单个非核心特征异常
P3 只记录(进看板,不告警)
· 各类统计量的日常变化
⭐ 绝大多数模型告警应该是 P2。 模型退化几乎总是渐进的,不需要半夜叫人。 把 P2 的东西设成 P0,是告警疲劳的头号来源。
🛠️ 三、六个降低误报的实用技巧
① 持续时间条件
结果对照
② 用同比而不是绝对值
结果对照
⭐ 同比是模型监控里性价比最高的一个技巧。 业务指标几乎都有强周期性,用绝对阈值一定会被周期打败。
③ 用分位数而不是均值
对照
均值容易被极端值带偏,一个异常大的值就能触发告警
⭐ 用 P50 / P90 更稳
④ 分人群看,避免辛普森效应
对照
总体 CTR 没变 —— 但可能是:
新用户 CTR 大跌 + 老用户小涨,正好抵消 💀
⭐ 核心指标至少按【新老用户】和【主要渠道】拆开看
🔗 这是第 14 章辛普森悖论在监控上的形态。
⑤ 告警要带上下文
结果对照
⭐ 好的告警应该让人在 30 秒内判断出「要不要现在处理」。 🔗 第 11 章会给一份排查手册的模板。
⑥ 告警收敛
信息关系
🧪 四、告警上线前必须做的一件事:回测
操作步骤
- 拿过去 60 天的历史数据
- 用你打算设的规则跑一遍
- 数一数:会报多少次警?
- 判断标准(经验值):
- · P0:一个月 ≤ 1 次 —— 多了就不是 P0
- · P1:一周 ≤ 2 次
- · P2:一天 ≤ 几次都可以(反正不推送)
- 再看:那几次已知的真实事故,这个规则能报出来吗?⭐
⭐ 第 ④ 步是关键:只看误报率会让你把阈值调得过松,什么都报不出来。 必须同时看漏报:拿历史上真实发生过的事故当测试集。
💡 这其实就是准确率-召回率权衡在告警设计上的应用 (🔗 ML基础 05)—— 告警系统本身就是一个分类器,你在给它选工作点。
📓 五、告警之外:值班手册和事后复盘
对照
收到告警之后,人应该知道做什么。
每个 P0/P1 告警都应该配一份【值班手册】(runbook):
· 这个告警意味着什么
· 先看哪三个看板
· 常见的三种原因和对应处理
· 什么情况下直接回滚
· 升级路径:什么时候叫谁
事后复盘要产出的东西:
| 产出 | 说明 |
|---|---|
| 时间线 | 问题何时开始、何时发现、何时恢复 |
| 发现延迟 ⭐ | 从发生到发现用了多久 —— 这个数字直接说明监控好不好 |
| 根因 | 不是「某人改错了」,而是「为什么这个错误能进到线上」 |
| 改进项 | 新增什么监控、什么检查能提前拦住 |
⭐ 「发现延迟」是衡量监控体系最好的单一指标。 比「有多少个告警」有意义得多 —— 后者只说明你加了多少规则。
💀 六、第 48 次
上面那个"12 周"的时间线不是虚构的形状。下面这个是它的具体数字版。
操作步骤
| 指标 | 数字 |
|---|---|
| 告警准确率 | 1 / 48 = 2.1% 💀 |
| 告警到确认(MTTA) | 27 分钟(而告警本身是准的) |
| 实际影响时长 | 53 分钟 |
| 本可以避免的部分 ⭐ | 22 分钟(占 42%) |
⭐ 这个事故的责任不在值班同学身上。 在 2.1% 准确率下,"先静音"是理性行为 —— 一个人不可能每次都为 2% 的概率立刻起身。 是告警设计逼出了这个行为。
🔑 复盘后他们做的三件事(都在本章讲过): 1. 这条规则从 P0 降到 P1,并加上"连续 10 分钟"的持续条件 2. 阈值改成和上周同一时段比,而不是和固定基线比 3. 新增一条真正的 P0:降级触发率 > 20%(这条在两个月回测里只会响 1 次)
结果:P0 从每月 24 次降到每月 0.5 次,而那唯一一次真事故仍然能被报出来。
📊 七、告警系统的四个数字
"我们有 30 个告警"不是一个指标。这四个才是:
| 数字 | 定义 | 目标 | 怎么量 |
|---|---|---|---|
| 准确率 | 真事故 / 总告警数 | P0 > 50% ⭐ | 每条告警强制打标(真/假) |
| 召回率 | 被告警抓到的事故 / 全部事故 | 越高越好 | 复盘时回填"这次有没有报" |
| MTTA | 告警触发 → 有人开始处理 | P0 < 5 分钟 | 从值班系统的确认时间取 |
| MTTR | 开始处理 → 指标恢复 | 见第 3 章 | 演练 + 真实事故 |
对照
⭐ 四个数字之间的关系:
一次事故的实际影响时长
= 发现延迟(监控好不好,第 5 章)
+ MTTA (告警可信不可信,本章)⭐
+ MTTR (回滚快不快,第 3 章)
⚠️ 很多团队只优化第一项和第三项,
而【中间这项常常是最大的一块】—— 因为它取决于人信不信你的告警
💡 一个立刻可做的动作:给每条告警加一个"这是真的吗"的按钮(👍/👎)。 两周之后你就有了每条规则的准确率 —— 然后把准确率低于 30% 的规则全部降级或删掉。 删掉一条噪声告警,比新增一条监控更能提升可靠性。
🧪 八、告警回测:可以直接跑的框架
第四节说"上线前必须回测"。这是一个能跑的版本:
import numpy as np, pandas as pd
def backtest_alert(series: pd.Series, rule, incidents, sustain=1):
"""series : 按时间索引的指标(建议按小时)
rule : 函数 (series) -> bool 数组,True 表示该时刻满足告警条件
incidents : [(开始时间, 结束时间)] 已知的真实事故
sustain: 需要连续满足几个时间点才真的告警 ⭐"""
raw = pd.Series(rule(series), index=series.index).fillna(False).astype(int)
# ⭐ 持续时间条件:连续 sustain 个点都满足才算一次告警
fired = raw.rolling(sustain, min_periods=sustain).sum() >= sustain
# ⭐ 相邻的连续告警合并成一次「事件」,否则一次故障会被数成几十次
grp = (fired != fired.shift()).cumsum()[fired]
events = [(g.index[0], g.index[-1]) for _, g in fired[fired].groupby(grp)]
# 召回:每个已知事故有没有在窗口内被报到
hit = [any(s <= e2 and e >= s2 for s2, e2 in events) for s, e in incidents]
# 误报:没有落在任何事故窗口内的告警事件
fp = [ev for ev in events
if not any(ev[0] <= e and ev[1] >= s for s, e in incidents)]
days = (series.index[-1] - series.index[0]).total_seconds() / 86400
return {
"告警次数": len(events),
"每月次数": round(len(events) / days * 30, 1), # ⭐ 直接对上分级标准
"召回": f"{sum(hit)}/{len(incidents)}",
"误报次数": len(fp),
"准确率": round(1 - len(fp) / max(len(events), 1), 3),
}
# 用法:把几套候选规则一起跑,挑工作点
rules = {
"绝对阈值 CTR<3%": lambda s: s < 0.03,
"同比 <上周70%": lambda s: s < s.shift(24 * 7) * 0.7, # ⭐ 去周期
"同比 <上周70% 且持续": lambda s: s < s.shift(24 * 7) * 0.7,
}
# backtest_alert(ctr_hourly, rules["同比 <上周70% 且持续"], known_incidents, sustain=3)
同样都能抓到事故,误报最少的才值得选
| 规则 | 每月次数 | 召回 | 准确率 | 结论 |
|---|---|---|---|---|
| 绝对阈值:CTR < 3% | 38.5 | 3 / 3 | 0.08 | 天天响 |
| 同比 < 上周 70% | 6.0 | 3 / 3 | 0.42 | 还是太多 |
| 同比 < 上周 70%,且持续 3 小时 | 1.5 | 3 / 3 | 0.83 | 选择它 |
三条规则的召回都是 3 / 3;前两条多出来的 37 次和 4.5 次,全是没有换来额外安全感的噪声。
⭐ 这个表就是本章的核心方法: 不要问"这个阈值合不合理",要问"在同样的召回下,哪个规则误报最少"。 🔗 这就是准确率-召回率曲线在告警设计上的用法 —— 你不是在调参数,你是在一条曲线上选工作点。
📐 三种阈值形式的对比
| 形式 | 优点 | 致命弱点 | 什么时候用 |
|---|---|---|---|
绝对阈值(< 3%) |
简单、好解释 | 被日内/周内周期打败 💀 | 只在没有周期性的指标上 |
| 环比(比 1 小时前) | 对突变敏感 | 对渐变完全失明 ⭐ | 抓管道故障 |
| 同比(比上周同时段)⭐ | 自动去周期 | 上周本身异常时会失效 | 业务指标的默认选择 |
| 和固定基线比(训练集/上线时) | 能抓慢漂移 ⭐ | 基线过期后全是噪声 | 特征分布、模型输出 |
💡 实践中的组合:业务指标用同比 + 固定基线两条线。 同比抓突变,固定基线抓慢漂移 —— 单独任何一条都会漏掉一整类问题。
⚠️ 告警设计的八个坑:
| 坑 | 后果 | 怎么修 |
|---|---|---|
| 一次故障报几十条 | 消息刷屏,真信息被淹 | 按根因收敛 + 合并连续告警 ⭐ |
| 告警只有指标名没有上下文 | 收件人无法判断,转手问人 | 带幅度、持续时间、负责人、手册链接 |
| 没有恢复通知 | 不知道问题好没好,一直挂着 | 恢复时也发一条 ⭐ |
| P0 太多 | 准确率崩,全员脱敏 💀 | 回测:P0 一个月 ≤ 1 次 |
| 规则上线后没人再看 | 阈值随业务增长早已失效 | 每季度重跑一次回测 ⭐ |
| 只在工作时间有值班 | 夜间事故第二天才发现 | 明确"夜间只保 P0"并说明后果 |
| 告警发到一个大群 | 责任分散,人人以为别人在看 | 指定到人,不是到群 ⭐ |
| 没有升级路径 | 值班的人搞不定就卡住了 | 15 分钟未确认自动升级到 TL |
📓 九、一份可以照抄的值班手册模板
流程图
⭐ 模板里最关键的是 ①:它把"这个告警意味着什么"变成了三个可以立刻看的数。 没有这一步,值班的人会从"打开看板"开始 —— 而那通常要 10 分钟。 🔗 第 11 章会把这套判断扩展成一棵完整的排查树。
🔗 十、和站内其他章的关系
| 相关的地方 | 和这一章的关系 |
|---|---|
| 第 5 章定阈值要回测 | 这一章展开了怎么回测 |
| 第 7 章信号时间轴 | 早期信号该设成 P2 而不是 P0 |
| ML基础 05准确率-召回率 | 告警设计就是在选工作点 |
| 智能体工程 12 | Agent 的终止与告警设计同理 |
✅ 检查点
- 为什么说「每天响 20 次的告警比没有告警更糟」?关键的误报率数字是多少?
- 告警四个级别的划分依据是什么?P0 的判据是什么?
- 为什么绝大多数模型告警应该是 P2?
- 六个降低误报的技巧里,哪个性价比最高?为什么?
- 分人群看是为了防什么?
- 好的告警应该让人在多久内做出判断?要带哪些上下文?
- 告警回测时,只看误报率会有什么问题?
- 衡量监控体系最好的单一指标是什么?为什么不是「告警数量」?
- 「第 48 次」那个事故里,告警准确率是多少?为什么说责任不在值班同学身上?他们复盘后做了哪三件事?
- 告警系统该看哪四个数字?一次事故的实际影响时长由哪三段组成?哪一段最常被忽略?
- 回测那张表里,三条规则的召回都是 3/3,这说明了什么?该选哪条?
- 绝对阈值 / 环比 / 同比 / 固定基线各自的弱点是什么?业务指标推荐怎么组合?
- 为什么告警要「指定到人」而不是发到大群?
- 值班手册里最关键的是哪一部分?为什么?
👀 答案
- 因为它让你以为自己有监控,实际上没人看。关键数字:误报率超过 50% 就在心理上失效了——人不会持续响应"多半是假的"信号,这是必然不是态度问题。
- 按处理紧迫度。P0 判据:多等 1 小时会造成不可逆损失。
- 因为模型退化几乎总是渐进的,不需要半夜叫人。把 P2 的东西设成 P0 是告警疲劳的头号来源。
- 用同比而不是绝对值。因为业务指标几乎都有强周期性(日内、周内),用绝对阈值一定会被周期打败(如"订单<1000"凌晨 3 点必然触发)。
- 防辛普森效应:总体 CTR 没变,可能是新用户大跌 + 老用户小涨正好抵消。
- 30 秒内判断出要不要现在处理。要带:特征的业务名和变化幅度、持续时间、该特征的重要性排名、可能的上游线索、负责人、排查手册链接。
- 会把阈值调得过松,什么都报不出来。必须同时看漏报——拿历史上真实发生过的事故当测试集,确认规则能报出来。
- 发现延迟(从问题发生到被发现用了多久)。比"有多少个告警"有意义得多,后者只说明你加了多少规则。
- 1/48 = 2.1%。责任不在人身上,是因为在 2.1% 准确率下"先静音"是理性行为——一个人不可能每次都为 2% 的概率立刻起身,是告警设计逼出了这个行为。三件事:①规则从 P0 降到 P1 并加"连续 10 分钟"的持续条件 ②阈值改成和上周同一时段比 ③新增一条真正的 P0(降级触发率 > 20%,回测两个月只响 1 次)。结果 P0 从每月 24 次降到 0.5 次,而真事故仍能报出来。
- 准确率、召回率、MTTA、MTTR。实际影响时长 = 发现延迟 + MTTA + MTTR。MTTA 最常被忽略——很多团队只优化监控和回滚,而中间这段取决于人信不信你的告警,常常是最大的一块。
- 说明前两条多出来的 37 次和 4.5 次告警全部是纯噪声,一点额外的安全感都没换来。该选「同比 <上周70% 且持续 3 小时」(每月 1.5 次,召回 3/3,准确率 0.83)。核心方法:不要问"这个阈值合不合理",要问"在同样的召回下哪个规则误报最少"——你是在准确率-召回率曲线上选工作点。
- 绝对阈值被日内/周内周期打败;环比对渐变完全失明;同比在上周本身异常时失效;固定基线在基线过期后全是噪声。业务指标推荐 同比 + 固定基线两条线:同比抓突变、固定基线抓慢漂移,单独任何一条都会漏掉一整类问题。
- 因为发到大群会责任分散,人人以为别人在看。要指定到具体的人,并配 15 分钟未确认自动升级。
- ① 30 秒判断那一段——它把"这个告警意味着什么"变成三个可以立刻看的数(降级率 / 上游表新鲜度 / 预测标准差)并各自指向下一步。没有它,值班的人要从"打开看板"开始,那通常要 10 分钟。
🛑 可以停在这里
⚡ 走神救援
⭐ 每天响 20 次的告警比没有告警更糟——它让你以为自己有监控。 误报率超过一半之后,人就不会再持续响应了;这是必然,不是态度问题。
四级里绝大多数模型告警应该是 P2(模型退化几乎总是渐进的)。把 P2 当 P0 是告警疲劳的头号来源。P0 的判据只有一条:多等一小时会造成不可逆损失。
降误报最值钱的两招:用同比不用绝对值(业务指标都有周期,绝对阈值必然被凌晨打败)和加持续时间条件。其余四招:分位数代替均值、分人群看、告警带上下文、按根因收敛。
⭐ 上线前必须拿历史回测,而且不能只看误报——要拿历史真实事故当测试集看漏报。 告警系统本身就是个分类器,你是在选工作点。
💀 那个「第 48 次」:两个月响了 48 次 P0 只有 1 次是真的,真出事时值班同学静音了,22 分钟后被客服叫醒。责任不在人身上——那个准确率下先静音是理性行为,是告警设计逼出来的。
⭐ 立刻能做的一件事:给每条告警加 👍/👎,两周后删掉准确率最低的那批规则。删一条噪声告警比加一条监控更能提升可靠性。
下一节 👉 09-特征重要性的三种谎言.md ⭐