AI 学习笔记(二十一):LLM Burn-Rate 告警与 Runbook 自动化最小实践

上一篇我们把 SLO、error budget 和 on-call 治理串了起来。
接下来最容易卡住的一步是:指标看板有了,但告警触发仍然靠“固定阈值 + 人工判断”,事故响应速度不稳定。

这篇继续生产运维主线,聚焦一个更可执行的闭环:
用 burn-rate 告警定位“预算正在被多快消耗”,再把 runbook 做成自动化动作。

先说结论:

  1. 只用静态阈值告警,往往要么太吵要么太迟
  2. burn-rate 的价值是把“是否该马上处理”变成预算消耗速度问题
  3. runbook 必须可自动执行,才能在夜间和高压场景稳定止血

1. 为什么 Burn-Rate 比固定阈值更适合线上治理

很多团队会给错误率或超时率设一个固定值,例如“错误率 > 5% 就报警”。
问题在于这个规则缺少业务语义:

  1. 峰值流量时,5% 可能意味着预算 30 分钟就耗尽
  2. 低流量时,5% 可能是短时抖动,不值得深夜把人叫起来
  3. 质量退化类问题(结构化输出漂移)常常不会直接触发“服务错误率”

burn-rate 的思路是看“预算消耗速度”,而不是只看“当前数值”。
如果 28 天预算被以 14 倍速度消耗,那就意味着两天左右就会把稳定性余量吃光,需要立刻干预。

这套逻辑对 LLM 应用尤其有价值,因为 LLM 事故常见为:

  1. 接口可用但结果质量明显变差
  2. 工具调用副作用上升(误写、误操作)
  3. 人工接管率突然上升导致值班压力暴涨

2. 最小 Burn-Rate 模型:先做两类预算

延续上一篇的 SLO 体系,建议先做两类预算:

  1. service_budget:可用性预算(成功率、延迟)
  2. quality_budget:质量预算(结构化输出成功率、关键路径通过率)

最小 burn-rate 可以理解为:

1
burn_rate = 当前窗口内的实际失败率 / 允许失败率

例如,目标成功率 99.5%,允许失败率是 0.5%。
如果最近 1 小时失败率是 2.5%,那么 burn-rate = 2.5 / 0.5 = 5。
这表示预算正在以 5 倍速度消耗。

在 LLM 场景里,建议分别计算:

  1. service_burn_rate
  2. quality_burn_rate
  3. side_effect_incident(高风险副作用事件,通常直接触发更高等级动作)

3. 告警规则建议:短窗口 + 长窗口组合

为了同时兼顾“快速发现”和“降低噪音”,最小可用规则可以从两档开始:

  1. P1:短窗口高 burn-rate(立即止血)
  2. P2:长窗口中等 burn-rate(尽快处理,避免恶化)

示例配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
burn_rate_alerts:
slo_window_days: 28
rules:
- level: P1
window: 1h
service_burn_rate_gt: 10
quality_burn_rate_gt: 8
action: "page_and_auto_mitigate"
- level: P2
window: 6h
service_burn_rate_gt: 4
quality_burn_rate_gt: 3
action: "page_and_manual_confirm"
side_effect_guard:
risky_write_incident_gt: 0
force_level: P1

这里的重点不是阈值精确,而是先形成“可执行规则 + 可审计动作”。
阈值可以在后续复盘里逐步调优。

4. Runbook 自动化:把“告警”变成“动作链”

值班体系里最常见的断点是:告警触发后,仍然依赖当班同学临场拼接动作。
更稳的方式是把 runbook 拆成固定动作链:

  1. Detect:识别告警等级和受影响能力
  2. Contain:先止血(降级、只读、切路由、冻结发布)
  3. Verify:自动执行关键路径健康检查
  4. Notify:结构化通知值班群与负责人
  5. Track:生成 incident 记录,沉淀后续复盘输入

建议至少把前 3 步做到自动化,避免人还没到位时系统继续失血。

5. 可直接接入服务层的最小自动化示例

下面这段 Node.js 示例演示了一个最小的告警处理器:
先判断是否需要进入止血模式,再选择动作 profile。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
export function decideMitigation(alert) {
const {
level,
serviceBurnRate,
qualityBurnRate,
riskyWriteIncidents,
} = alert;

if (riskyWriteIncidents > 0) {
return { mode: "emergency-freeze", reason: "risky-write-incident" };
}

if (level === "P1" || serviceBurnRate >= 10 || qualityBurnRate >= 8) {
return { mode: "degrade-readonly", reason: "high-burn-rate" };
}

if (level === "P2" || serviceBurnRate >= 4 || qualityBurnRate >= 3) {
return { mode: "canary-only", reason: "medium-burn-rate" };
}

return { mode: "observe", reason: "within-budget" };
}

可以再配一个动作执行清单:

1
2
3
4
5
6
7
8
9
10
11
mitigation_profiles:
degrade-readonly:
- disable_high_risk_tools
- enable_provider_fallback
- reduce_context_window
- freeze_release_pipeline
- run_smoke_checks
canary-only:
- force_low_traffic_canary
- tighten_release_gate
- run_regression_eval

这样做的价值是:
同样的告警,在不同值班人手里能得到一致结果,降低“处理风格差异”带来的二次风险。

6. 落地建议:先小范围闭环,再扩展覆盖

如果你打算一周内落地,建议按下面节奏推进:

  1. Day 1:为服务可用性和质量各定义 1 条 SLO 与预算
  2. Day 2:实现 1h/6h burn-rate 计算与告警规则
  3. Day 3:把 P1 自动止血动作接入开关(只读、冻结发布、回切路由)
  4. Day 4:做一次夜间模拟演练,验证告警到止血链路时延
  5. Day 5:补 incident 模板和复盘字段,形成持续调优闭环

先做到“可执行、可回放、可复盘”,再讨论更复杂的智能分级与自动恢复。
对多数团队来说,这已经能显著降低线上波动时的响应不确定性。

总结

把 SLO 写进文档只是第一步,真正决定稳定性的,是预算消耗时系统是否会自动进入正确动作。
burn-rate 让告警更贴近风险,runbook 自动化让处置更可预测。

如果这周你只做一件事,我建议优先完成:
将 P1 burn-rate 告警直接绑定一个“可自动执行且可回滚”的止血 profile。

参考资料

本文永久链接: https://www.mulianju.com/learning-notes/ai-learning-notes-llm-burn-rate-alert-runbook-automation-minimal-practice/