第 7 章 · 可观测性体系(Metrics / Logs / Traces)
本章构建 三位一体可观测性,支撑架构决策、SLO 治理与故障定位,并为 L3 认证提供可观测证据。
前置:PaaS ch6、ch10;小紫云计算监控;架构 ch01 NFR。
7.1 三支柱与关联模型
| 支柱 | 回答问题 | 工具 | 贤紫对应 |
|---|---|---|---|
| Metrics | 多快、多忙、多错? | Prometheus + Grafana | 集群插件 / prometheus |
| Logs | 发生了什么? | Loki / ELK | loki + Explore |
| Traces | 请求经过谁、慢在哪? | Jaeger | jaeger OTLP 4317/4318 |
关联键:traceId + spanId + service + namespace。
traceId=7f3a9c2e
├─ gateway 12ms
├─ order-api 85ms ── mysql 42ms / redis 3ms
└─ notify-worker 210ms (async)
| 场景 | 先看 | 再看 |
|---|---|---|
| 错误率突增 | Metrics 5xx | Logs ERROR + traceId |
| P99 变慢 | histogram | Traces 最长 Span |
| 单用户投诉 | Logs userId | Traces 该 traceId |
7.2 指标设计:RED / USE / SLI
RED(每个核心 API)
| 字母 | 指标 | PromQL 思路 |
|---|---|---|
| R | Rate | sum(rate(http_requests_total[5m])) |
| E | Errors | 5xx rate / total rate |
| D | Duration | histogram_quantile(0.99, ..._bucket) |
USE(资源层):Utilization / Saturation / Errors — CPU%、队列深度、OOM。
社区电商 SLI 建议
| SLI | SLO 示例 |
|---|---|
可用性 1-5xx/total | 99.9%/月 |
| 下单 P99 | < 300ms |
| 订单创建成功率 | > 99.95% |
埋点规范
| 规则 | 正确 | 反例 |
|---|---|---|
| 单位后缀 | _seconds、_total | 无单位 latency |
| 标签基数 | method, status | user_id 作 label |
| Histogram | 覆盖 P50~P99 | 仅 3 个桶 |
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: order-api
namespace: monitor
spec:
selector:
matchLabels:
app: order-api
endpoints:
- port: metrics
interval: 15s
7.3 日志规范与 LogQL
{
"time": "2026-08-18T10:00:00.123Z",
"level": "INFO",
"traceId": "7f3a9c2e8b1d4f6a",
"service": "order-api",
"msg": "order created",
"orderId": "ORD202608180001",
"durationMs": 85
}
| 规则 | prod 要求 |
|---|---|
| 结构化 JSON 一行一条 | ✓ |
| traceId 必填 | 与 Jaeger 一致 |
| 默认 INFO | ERROR 含 stacktrace |
| 禁止明文 | 密码、token、身份证 |
{namespace="prod-app", app="order-api"} | json | level="ERROR"
{namespace="prod-app"} | json | traceId="7f3a9c2e8b1d4f6a"
sum(count_over_time({app="order-api"} | json | level="ERROR" [1m]))
7.4 分布式追踪与采样
| 传播头 | 说明 |
|---|---|
traceparent | W3C 标准(推荐) |
X-Trace-Id | 遗留兼容 |
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(
OTLPSpanExporter(endpoint="jaeger.monitor.svc.cluster.local:4317", insecure=True)
))
FastAPIInstrumentor.instrument_app(app)
| 策略 | 采样率 | 适用 |
|---|---|---|
| always_on | 100% | staging |
| traceidratio | 5%~10% | prod |
| 错误强制 | ERROR 100% | 叠加比例采样 |
数值:日请求 2000 万、10% 采样、均 5 span → 约 1 亿 span/天;需规划 Jaeger 存储保留 7 天。