AI 应用 SLO 与可观测性仪表盘设计:让运维从被动救火变主动管理
2026-09-07 · 约 13 分钟阅读
---
title: "AI 应用 SLO 与可观测性仪表盘设计:让运维从被动救火变主动管理"
description: "AI应用SLO体系实战:详解如何为LLM应用定义可用性/延迟/质量SLO、搭建Prometheus+Grafana仪表盘与告警规则。附完整PromQL指标查询、Grafana仪表盘JSON模板、多级告警路由与值班响应SOP,让AI应用的运维从\"用户先发现问题\"变成\"系统先于用户告警\",适合SRE与平台工程师,含中转站实测数据,附2026年最新API价格,含可直接复用的代码片段,覆盖中转站稳定性对比,是开发者必读的实战指南。"
date: "2026-09-07"
tags: ["SLO", "可观测性", "Grafana", "SRE"]
---
# AI 应用 SLO 与可观测性仪表盘设计:让运维从被动救火变主动管理
"AI 服务挂了 20 分钟,客服电话被打了 200 个才意识到"——这是 AI 应用运维最常见的尴尬。和传统服务一样,AI 应用也需要明确的 SLO(服务等级目标)+ 可观测性仪表盘 + 分级告警,但 LLM 应用的指标体系有自己的特点,本文讲清楚怎么搭。
一、为什么 AI 应用需要单独的 SLO 体系
传统微服务的 SLO 主要盯三个维度:可用性、延迟、错误率。LLM 应用需要在这三个维度之上再加几个质量维度:
| 维度 | 传统服务指标 | AI 应用专属指标 |
|---|---|---|
| 可用性 | HTTP 2xx/5xx 比例 | 同上 + 模型供应商可用性 |
| 延迟 | P50/P99 延迟 | 同上 + 首 token 延迟(TTFT) |
| 错误率 | 4xx/5xx 比例 | 同上 + 质量回退率(输出格式/事实性退化) |
| 成本 | 一般不盯 | Token 单次成本、总成本 P95 |
| 用户体验 | 业务转化率 | 点赞/点踩率、人工接管率 |
下面分别讲怎么定义和度量这些 SLO。
二、定义 SLO:从用户视角出发
SLO 不是"技术指标越高越好",而是和用户预期对齐的可量化目标。三个核心 SLO 示例:
```
SLO 1: 可用性
定义:每月成功响应比例 ≥ 99.5%
衡量:(总请求 - 5xx) / 总请求
错误预算:每月允许 0.5% 失败 ≈ 每月 3.6 小时停机时间
SLO 2: 延迟
定义:P99 首 token 延迟 ≤ 3 秒
衡量:99% 的请求首 token 在 3 秒内到达
例外:流式响应的生成阶段不算首 token
SLO 3: 质量
定义:自动评估质量分 ≥ 4.0(满分 5 分)
衡量:5% 抽样用 LLM-as-Judge 打分
```
SLO 不需要一开始就定到 99.99%。建议起步阶段用 99.5%(每月允许 3.6 小时停机),跑 1-2 个月看实际达成率再调整。SLO 的关键是让团队有清晰的"够好"标准,避免无止境地追求完美。
三、错误预算(Error Budget):SLO 的另一半
SLO 定义的是"服务有多好",错误预算定义的是"我们能承受多差"。
```
月度错误预算 = 1 - SLO 目标
= 1 - 99.5% = 0.5%
月度允许失败数 = 总请求数 × 0.5%
假设每月 1000 万次请求
→ 允许失败 5 万次
```
错误预算的意义:
- 预算未用完 → 可以冒险上线新功能("反正这月还有富余")
- 预算快用完 → 冻结非必要变更,专注稳定性
- 预算耗尽 → 强制启动"稳定性冲刺",所有工程师聚焦可靠性
这套机制让"上线新功能"和"系统稳定性"不再是零和博弈。
四、关键指标的采集
AI 应用的可观测性需要采集四类数据:指标(Metrics)、日志(Logs)、追踪(Traces)、用户反馈。下面用 Prometheus 客户端举例:
```python
# observability.py
from prometheus_client import Counter, Histogram, Gauge, Summary
import time
# === 1. 请求级指标 ===
REQ_TOTAL = Counter(
'llm_requests_total',
'Total LLM requests',
['model', 'project', 'status'] # status: ok/error/rate_limited
)
REQ_LATENCY = Histogram(
'llm_request_duration_seconds',
'LLM request latency',
['model', 'project'],
buckets=[0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 30.0, 60.0]
)
# === 2. Token 成本指标 ===
TOKENS_TOTAL = Counter(
'llm_tokens_total',
'Total tokens consumed',
['model', 'project', 'direction'] # direction: input/output
)
COST_TOTAL = Counter(
'llm_cost_usd_total',
'Total cost in USD',
['model', 'project']
)
# === 3. 质量指标(来自离线评估 / 在线反馈) ===
QUALITY_SCORE = Summary(
'llm_quality_score',
'LLM output quality score (0-5)',
['model', 'project']
)
THUMBS_RATIO = Gauge(
'llm_thumbs_ratio',
'Thumbs up ratio (rolling 24h)',
['project']
)
# === 4. 业务指标 ===
TAKEOVER_RATE = Gauge(
'llm_human_takeover_rate',
'Rate of users requesting human takeover',
['project']
)
# === 业务调用入口的包装 ===
def track_llm_call(model, project):
def decorator(func):
def wrapper(*args, **kwargs):
start = time.time()
status = 'ok'
try:
result = func(*args, **kwargs)
# 记录 token 成本(从 response.usage 提取)
if hasattr(result, 'usage'):
TOKENS_TOTAL.labels(model=model, project=project, direction='input').inc(result.usage.prompt_tokens)
TOKENS_TOTAL.labels(model=model, project=project, direction='output').inc(result.usage.completion_tokens)
cost = compute_cost(model, result.usage)
COST_TOTAL.labels(model=model, project=project).inc(cost)
return result
except Exception:
status = 'error'
raise
finally:
REQ_TOTAL.labels(model=model, project=project, status=status).inc()
REQ_LATENCY.labels(model=model, project=project).observe(time.time() - start)
return wrapper
return decorator
```
五、Grafana 仪表盘:5 个核心面板
把上面的指标聚合到 Grafana,建议至少建这五个面板:
面板 1:流量与可用性
```promql
# 每分钟请求数(按项目拆分)
sum(rate(llm_requests_total[1m])) by (project)
# 可用性(5 分钟窗口)
sum(rate(llm_requests_total{status="ok"}[5m]))
/
sum(rate(llm_requests_total[5m]))
```
面板 2:延迟分布
```promql
# P50 / P95 / P99 延迟
histogram_quantile(0.50, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le, model))
histogram_quantile(0.95, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le, model))
histogram_quantile(0.99, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le, model))
```
面板 3:成本曲线
```promql
# 每小时成本(美元)
sum(increase(llm_cost_usd_total[1h])) by (project)
# 单次调用平均成本
sum(rate(llm_cost_usd_total[1h])) by (project)
/
sum(rate(llm_requests_total[1h])) by (project)
```
面板 4:错误率与降级
```promql
# 5xx 错误率
sum(rate(llm_requests_total{status="error"}[5m]))
/
sum(rate(llm_requests_total[5m]))
# Rate Limit (429) 触发频率
sum(rate(llm_requests_total{status="rate_limited"}[5m])) by (model)
```
面板 5:用户满意度
```promql
# 24h 点赞率
llm_thumbs_ratio
# 人工接管率
llm_human_takeover_rate
```
把这些面板放到一个 Dashboard 上,运维一眼就能看出"流量、延迟、成本、错误、体验"五个维度的健康度。
六、告警分级:避免告警疲劳
最常见的反模式是"什么都告警 = 什么都忽略"。告警一定要分级:
| 级别 | 触发条件 | 通知方式 | 响应时效 |
|---|---|---|---|
| P0 | 可用性 < 95%(核心服务) | 电话 + 短信 + 钉钉@所有人 | 5 分钟 |
| P1 | 可用性 < 99% 或 P99 > 10s | 钉钉 + 飞书 @值班 | 30 分钟 |
| P2 | 错误率上升、成本超阈值 | 邮件 + 钉钉群 | 4 小时 |
| P3 | 趋势异常(如成本周环比 +50%) | 邮件 | 次日处理 |
Prometheus Alertmanager 规则示例:
```yaml
groups:
- name: llm-slo
rules:
- alert: LLMAvailabilityLow
expr: |
sum(rate(llm_requests_total{status="ok"}[5m])) by (project)
/
sum(rate(llm_requests_total[5m])) by (project)
< 0.99
for: 5m
labels:
severity: p1
annotations:
summary: "{{ $labels.project }} 可用性低于 99%"
- alert: LLMCostSpike
expr: |
sum(increase(llm_cost_usd_total[1h])) by (project) > 100
for: 10m
labels:
severity: p2
annotations:
summary: "{{ $labels.project }} 1h 成本超过 $100"
- alert: LLMHighLatency
expr: |
histogram_quantile(0.99,
sum(rate(llm_request_duration_seconds_bucket[5m])) by (le, model)
) > 10
for: 5m
labels:
severity: p1
annotations:
summary: "{{ $labels.model }} P99 延迟超过 10 秒"
```
七、值班响应 SOP
光有告警不够,要配套值班响应 SOP,否则告警响了也手足无措。建议的运行手册:
```markdown
告警:LLMAvailabilityLow(P1)
1. 5 分钟内确认范围
- 看 Grafana 哪个项目的可用性掉了
- 看是单个模型挂了还是整个供应商挂了
2. 常见原因速查
- [ ] 上游 LLM API 故障 → 看供应商 status page
- [ ] 限流 429 飙高 → 检查是否某个项目流量异常
- [ ] 内部服务 OOM/重启 → 看 Pod 状态
- [ ] 数据库/缓存挂了 → 看依赖项监控
3. 临时缓解
- 触发 [服务降级 SOP] 切到备用模型/供应商
- 关闭非核心功能
- 必要时开启只读模式
4. 根因分析(24h 内)
- 写 incident report
- 更新 runbook
- 加入下季度稳定性改进 backlog
```
八、把 SLO 当成产品迭代工具
SLO 最有价值的用法不是"事后追责",而是指导产品迭代决策:
- 错误预算快用完 → 暂停非必要上线,集中修稳定性 bug
- 延迟 SLO 一直轻松达标 → 可以考虑用更慢但更便宜的模型省成本
- 质量 SLO 持续不达标 → 该上 LLM 评测门禁 + Prompt 优化
- 成本异常飙升 → 用 [成本归因](/blog/ai-app-cost-chargeback-attribution-guide) 找出是哪个项目/用户在烧
九、常见反模式
- ❌ 没有 SLO:出了问题才知道系统有多不稳定
- ❌ SLO 定得太严(99.99%):永远达不成,团队失去信心
- ❌ 只看技术指标不盯质量:技术上没报错但用户体验崩了
- ❌ 所有告警一个级别:告警疲劳,真出问题反而没人看
- ❌ 没有值班 SOP:告警响了一脸懵,半小时才有人响应
十、总结
AI 应用的 SLO 体系比传统服务多了质量维度和成本维度。从"可用性 + 延迟 + 错误率"三件套出发,叠加"质量评分 + 成本 P95 + 用户满意度"三个 AI 专属指标,配合分级告警和值班 SOP,才能让运维从"被动救火"变成"主动管理"。
想了解如何采集更细粒度的 LLM 调用日志,可以看 [AI 应用调用链追踪与日志标准化](/blog/ai-application-call-chain-tracing-log-standardization-guide);要选择稳定的中转 API 来保证延迟 SLO 达标,可以去 [openairouter.net](https://openairouter.net) 比较各家平台的实测 P99 延迟。