深色模式
可观测性反模式
摘要:可观测性项目失败很少是因为工具不好,多半是掉进了几个常见陷阱:指标一大堆却没一个能定位、告警响个不停却没人看、买了平台却依然靠猜。本文列出十类反模式,给出识别信号与纠正动作。
适用环境
bash
# 反模式自查:先量一量现状
curl -s http://127.0.0.1:9090/api/v1/label/__name__/values \
| python3 -c "import sys,json;print('指标总数:',len(json.load(sys.stdin)['data']))"
# 告警数量与静默数量
curl -s http://127.0.0.1:9093/api/v2/alerts | python3 -c \
"import sys,json;d=json.load(sys.stdin);print('活跃告警:',len(d))"
curl -s http://127.0.0.1:9093/api/v2/silences | head -c 200
# 看板总数(>50 且没人看 = 典型症状)1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
操作步骤
1. 反模式一:为监控而监控,指标一大堆但无 SLO
识别信号:看板几十个、指标上千种,但没人说得清"服务现在健不健康"。 纠正:先定义 3-5 个 SLI(成功率、延迟、吞吐),围绕它们建看板,其余指标降级为"排查时才看"。
2. 反模式二:把日志当指标用
bash
# 错误做法:用日志 grep 统计错误率(慢且不准)
grep -c 'ERROR' /var/log/app.log1
2
2
识别信号:看板上写着 count(grep ERROR) 之类的计数。 纠正:错误率必须是计数器指标,日志只负责承载明细上下文。
3. 反模式三:高基数标签进指标
promql
# 灾难写法:每个用户一条时间序列
http_request_duration_seconds{user_id="10086"}1
2
2
纠正:改用 http.route、分桶哈希或干脆放到日志/链路里。
4. 反模式四:告警基于原因而非症状
yaml
# 反模式:CPU 高就告警(用户可能毫无感知)
- alert: HighCPU
expr: cpu_usage > 0.8
# 正确:基于用户可感知的症状
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) > 0.01
for: 5m1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
5. 反模式五:告警无 for、无分级、无处置文档
识别信号:告警一响就是 P1,值班人只能靠经验猜。 纠正:每条告警必须有 for 持续时间、severity 分级和对应的处置手册链接(或步骤)。
6. 反模式六:全量采样链路
bash
# 反模式:100% 采样,成本失控且压垮 Collector
export OTEL_TRACES_SAMPLER=always_on1
2
2
纠正:头部采样 1%-10%,配合尾部采样保留错误与慢请求。
7. 反模式七:链路断在异步与消息队列
识别信号:trace 里只有入口 span,后面全没了。 纠正:显式传递 context(消息头里带 traceparent),并为异步任务创建 linked span。
8. 反模式八:日志与链路没有统一标识
bash
# 没有 trace_id 的日志,等于无法从日志跳链路
{"level":"error","msg":"failed"} # 反模式
{"level":"error","msg":"failed","trace_id":"4bf92f..."} # 正确1
2
3
2
3
9. 反模式九:只看技术指标不看业务指标
识别信号:所有组件灯都是绿的,但订单量掉了一半没人发现。 纠正:为核心业务流(下单、支付、注册)建立独立的业务指标与告警。
10. 反模式十:从不复盘、从不清理
bash
# 定期清理不看的看板与不触发的告警(建议每季度)
# 检查哪些告警从未触发过:多半是阈值写错或已失效
curl -s http://127.0.0.1:9090/api/v1/rules | python3 -c \
"import sys,json;d=json.load(sys.stdin)['data']
for g in d['groups']:
for r in g['rules']:
print(r['name'], r.get('state'))" | sort | uniq -c | head1
2
3
4
5
6
7
2
3
4
5
6
7
验证
bash
# 1) 每个服务都有明确的 SLI 定义(人工核对服务清单)
# 2) 告警数量收敛(活跃告警应有明确归属与处置动作)
curl -s http://127.0.0.1:9093/api/v2/alerts | python3 -c \
"import sys,json;print('当前告警数:',len(json.load(sys.stdin)))"
# 3) 日志里 trace_id 覆盖率
kubectl logs deploy/demo --tail=100 | grep -c 'trace_id'
# 4) 指标基数在预算内
curl -s http://127.0.0.1:9090/api/v1/status/tsdb | python3 -c \
"import sys,json;print('series:',json.load(sys.stdin)['data']['headStats']['numSeries'])"1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
常见坑
WARNING
"把所有数据都采集了再说"是最昂贵的反模式。存储、检索与人力成本会先于价值到来,最终因成本过高被整体砍掉。
WARNING
告警治理只做降噪不做分级,会让真正严重的问题淹没在噪声里。请同时做"减少无效告警"和"明确严重级别"两件事。
DANGER
可观测性数据里包含大量业务与用户行为信息。若平台权限管理松散(所有人可见全部数据),会形成远超预期的内部数据暴露面,务必按服务与敏感度做分权。