深色模式
可观测性三支柱深化
摘要:指标告诉你"出问题了",链路告诉你"出在哪个服务哪一跳",日志告诉你"具体报了什么错"。三者的价值不在各自独立,而在于能否用同一组标识互相跳转。本文给出落地的协同方案与一份端到端排查演练。
适用环境
bash
# 确认三套数据都能查到(以 Prometheus + Loki + Tempo 为例)
curl -fsS http://127.0.0.1:9090/-/healthy # 指标
curl -fsS http://127.0.0.1:3100/ready # 日志
curl -fsS http://127.0.0.1:3200/ready # 链路
# 确认应用已输出带 trace_id 的日志
kubectl logs deploy/demo --tail=5 2>/dev/null | head -51
2
3
4
5
6
7
2
3
4
5
6
7
操作步骤
1. 明确三支柱的分工
| 支柱 | 回答的问题 | 成本 | 典型工具 |
|---|---|---|---|
| Metrics 指标 | 有多少、变快还是变慢 | 低,可长期保留 | Prometheus |
| Logs 日志 | 具体发生了什么 | 高,需控制采样与保留 | Loki / ES |
| Traces 链路 | 请求经过哪些服务、哪一跳慢 | 中,需采样 | Tempo / Jaeger |
黄金排查顺序:指标告警 → 链路找慢的一跳 → 日志看具体错误。
2. 用统一标识打通三者
yaml
# 应用日志必须输出 trace_id / span_id,这是三支柱互通的钥匙
# 结构化日志示例(JSON)
{"level":"error","msg":"order create failed","trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","user_id":"10086","err":"timeout"}1
2
3
2
3
3. 配置日志到链路的跳转(Grafana 数据源 derivedFields)
yaml
# Grafana Loki 数据源配置片段
derivedFields:
- name: TraceID
matcherRegex: '"trace_id":"(\w+)"'
url: '$${__value.raw}'
datasourceUid: tempo1
2
3
4
5
6
2
3
4
5
6
4. 配置指标到链路的跳转(exemplars)
yaml
# Prometheus 抓取配置需开启 exemplar 存储
scrape_configs:
- job_name: app
metrics_path: /metrics
static_configs:
- targets: ['127.0.0.1:8080']1
2
3
4
5
6
2
3
4
5
6
bash
# 应用侧暴露 exemplar:直方图指标样本上附带 trace_id
curl -s http://127.0.0.1:8080/metrics | grep -m3 ' # ' | head -31
2
2
5. 用 TraceID 反查日志
bash
# Loki 查询:找出某次失败请求的全部日志
logcli query '{app="demo"} | json | trace_id="4bf92f3577b34da6a3ce929d0e0e4736"' --limit=1001
2
2
6. 端到端演练一次排查
bash
# 1) 指标告警:P99 延迟升高
curl -s 'http://127.0.0.1:9090/api/v1/query' \
--data-urlencode 'query=histogram_quantile(0.99, sum(rate(http_server_request_duration_seconds_bucket[5m])) by (le))' | head -c 300
# 2) 找到慢请求的 trace_id(从 exemplar 或日志)
# 3) 在链路系统里打开该 trace,定位耗时最长的 span
curl -s 'http://127.0.0.1:3200/api/traces/4bf92f3577b34da6a3ce929d0e0e4736' | head -c 300
# 4) 用同一 trace_id 查日志,拿到具体错误堆栈1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
验证
bash
# 1) 日志里确实带 trace_id
kubectl logs deploy/demo --tail=20 | grep -o 'trace_id":"[a-f0-9]*' | head -3
# 2) 链路能被检索到
curl -s 'http://127.0.0.1:3200/api/search?tags=&limit=5' | head -c 200
# 3) 在 Grafana 里点击日志行的 trace_id 能跳转到链路详情(人工确认一次)
# 4) 指标 exemplar 存在
curl -s http://127.0.0.1:8080/metrics | grep -c 'trace_id'1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
常见坑
WARNING
三套系统各自用一套服务名(order-svc、order_service、svc-order),导致无法互相跳转。请用统一的 service.name 命名规范,并从 CI 或注册中心自动生成。
WARNING
日志里没有 trace_id 是打通失败最常见的根因。优先解决日志框架与 OTel 的 MDC/context 集成,而不是先买更贵的平台。
DANGER
为"打通"而在日志里打印完整请求体和用户敏感信息(手机号、身份证、token),会带来严重的数据合规风险。日志字段必须做脱敏设计,敏感字段只打印哈希或掩码。