告警条件设计:基于指标、日志、事件
告警条件的设计,说白了就是回答三个问题:什么时候要报警?用什么数据来判断?怎么组合才不误报? 我个人习惯把数据源分成三类 —— 指标、日志、事件。这三类各有脾气,组合起来才能覆盖真实场景。
核心原则:单一数据源容易漏报或误报,交叉验证才是王道。
1. 指标型条件 —— 数字会说话
指标是最常见的告警源。CPU、内存、延迟、错误率……这些都是数值型时间序列。我刚开始做监控时,只会设一个静态阈值,比如 CPU > 90% 就报警。结果半夜被叫起来,发现只是业务高峰期的正常波动。后来我学会了动态阈值和速率派生。
常见指标模式
- 静态阈值:直接比较数值大小。适合已知安全边界的指标。
- 同比/环比:和过去同一时段比。适合有周期性的业务。
- 聚合速率:每秒/每分钟的变化率。比如 HTTP 5xx 速率突增。
- 百分位值:P99 延迟 > 500ms,比平均值更敏感。
举个 PromQL 的例子,检测 5 分钟内的错误率持续上升:
# 5分钟错误率同比上周同一时段增长超过50%
(
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
)
/
(
sum(rate(http_requests_total{status=~"5.."}[5m] offset 1w))
/
sum(rate(http_requests_total[5m] offset 1w))
) > 1.5
💡 经验:不要用平均值。我踩过的坑 —— 平均延迟正常,但 P99 已经飙到 3 秒,前端用户早炸了。用百分位或分位数更靠谱。
2. 日志型条件 —— 文字里藏着凶器
日志告警比指标更直接。但你想想看,每天几 TB 的日志,总不能每条都报警。关键是从非结构化文本中提取结构化信号。
日志告警的三种粒度
| 粒度 | 例子 | 适用场景 |
|---|---|---|
| 关键字匹配 | “OutOfMemoryError” | 已知异常模式 |
| 正则表达式 | “Connect timeout after \d+ms” | 可变参数的错误 |
| 模式频率 | 1分钟内同一错误出现10次以上 | 短时故障风暴 |
我曾经因为只配了关键字告警,忽略了“Connection reset by peer”这种变体,结果服务挂了半小时才被用户通知。后来我改用正则并加了频率窗口:
# 示例:Elasticsearch 查询
{
"query": {
"bool": {
"must": [
{ "regexp": { "message": "Error|Exception|Failed" } },
{ "range": { "@timestamp": { "gte": "now-1m" } } }
]
}
},
"aggs": {
"error_count": { "value_count": { "field": "message.keyword" } }
}
}
⚠️ 注意:日志量级过大时,聚合查询会成为性能瓶颈。建议先做流式统计(比如 Flink、Kafka Streams),落盘前就判断是否超标。
3. 事件型条件 —— 变化本身就是信号
事件不是数值,也不是文本,而是“发生了某件事”:部署上线、配置变更、服务重启、证书过期……这类告警往往需要和其他数据源联动。
典型事件告警场景
- 部署后指标异常:新版本上线后 5 分钟内错误率突增。
- 配置变更触发的连锁反应:某服务的超时配置被修改,随后下游出现大量 503。
- 证书即将过期:提前 7 天告警,你总不想半夜去换证书吧?
事件告警的难点在于关联性。一个事件本身可能无害,但组合起来就要命。我自己的做法是给每个事件打标签(name、source、severity),然后用规则引擎做时序窗口匹配:
# 伪代码:事件+指标组合
WHEN
event.name == "deploy_start" AND
metric.error_rate > 5% AND
duration 300s
THEN
alert("部署疑似引入回归,请回滚")
4. 组合条件 —— 别让单点骗了你
单一数据源的告警就像单腿走路。我最怕的误报就是“日志里出现了 Error 但业务正常”,或者“CPU 高但负载低”。所以条件设计时,我习惯用与/或/非逻辑组合:
| 组合方式 | 含义 | 例子 |
|---|---|---|
| AND | 全部满足才告警 | 指标高 AND 日志里有对应错误 |
| OR | 任一满足就告警 | P99 > 500ms OR 错误率 > 5% |
| NAND | 不满足所有 | 用于抑制告警:维护窗口内不告警 |
| 时序窗口 | 一段时间内持续异常 | 5 分钟内连续 3 个采集点都超标 |
别忘了沉默期和衰减。同一问题重复告警 = 噪音。我一般设置相同告警 1 小时内只发一次,除非状态改变。
5. 一张图看清告警条件设计
下面这张图把三类数据源和组合逻辑串起来了。你可以把它当作自己设计告警规则的“地图”。
6. 避坑指南
最后说几个我踩过的坑,希望你别再重蹈覆辙。
- 阈值设得太死:我曾给磁盘使用率设了 85% 告警,结果每周扩一次盘。后来改为 80% 警告、90% 严重,配合预测增长趋势,清净多了。
- 忽略日志采样:日志量大的时候,全文索引慢得可怕。我用 Logstash 先做采样,只保留 ERROR 级别且去重后的日志,告警性能提升 10 倍。
- 事件没有去重:一次集群滚动重启,产生了 3000 个“服务停止”事件。如果没有窗口去重,告警系统直接崩溃。我当时加了 5 分钟内相同 event_id 只发一次。
- 组合条件缺少超时:AND 条件里,如果两个信号时间差太大(比如指标滞后事件 2 分钟),告警就不会触发。我一般用 1 分钟的滑动窗口做对齐。
调试小技巧:先在不发送真实告警的干跑模式下测试规则。用历史数据回放,看规则能不能命中已知故障。我就靠这个发现了不少漏报。
告警条件设计不是一蹴而就的。你需要根据业务变化持续调整。指标、日志、事件这三驾马车,用好了就是你的千里眼和顺风耳。希望这一章的内容能帮你少走些弯路。