可观测性进阶:从遥测关联到持续剖析
接入日志、指标和链路并不等于建立了可观测性。如果三类数据时间不一致、资源属性不同、没有 Trace ID,排障时仍然需要人工猜测。可观测性进阶的核心,是让告警可以跳转到相关链路、日志和代码资源消耗,并控制采集量、标签基数和存储成本。
本文建立在 OpenTelemetry 入门基础上,重点讨论信号关联、采样、遥测管道、持续剖析和数据治理。Profiles 仍在持续演进,生产使用前应核对当前规范与所选后端的支持状态。
一、四类信号分别回答什么
| 信号 | 主要问题 | 典型用途 |
|---|---|---|
| Metrics | 系统整体发生了什么 | 告警、趋势、容量与 SLO |
| Logs | 某个时刻记录了什么事件 | 错误细节、审计和上下文 |
| Traces | 一次请求经过了哪些组件 | 分布式延迟和依赖定位 |
| Profiles | 哪段代码消耗 CPU、内存或等待时间 | 性能热点、泄漏和锁等待 |
四类信号不是相互替代。指标发现影响范围,链路找到慢在哪个服务,日志解释具体错误,剖析定位到函数或调用栈。
二、先统一资源身份
不同信号必须使用一致的资源属性,否则无法关联。推荐至少统一:
service.name
service.namespace
service.version
deployment.environment.name
host.name 或 k8s.pod.uid
cloud.region / cloud.availability_zone
service.name 不应在每次发布变化;版本放在 service.version。Pod 名称、请求 ID、用户 ID 等高变化值不应成为指标标签,但可以作为日志字段或 Trace 属性,并遵守隐私与脱敏规则。
三、打通 Trace 与日志
应用日志应包含当前请求的 Trace ID 和 Span ID。这样从一条错误日志可以跳到完整调用链,从慢 Span 也能查询同一请求的日志。
一个结构化日志示例:
{
"timestamp": "2026-10-18T10:00:00Z",
"severity": "ERROR",
"service.name": "order-api",
"service.version": "2.4.1",
"trace_id": "...",
"span_id": "...",
"event.name": "order.create.failed",
"error.type": "DependencyTimeout",
"message": "inventory request timed out"
}
不要把口令、Token、完整证件号码、Cookie 和请求正文无差别写入日志。日志字段设计应有数据分类和保留策略。
四、从告警跳到证据
一条高质量告警应带有:
- 服务、环境、区域和版本;
- 用户影响与 SLO 状态;
- 触发时间和持续时间;
- Dashboard、Trace 查询和日志查询链接;
- 最近变更、负责人和 Runbook;
- 安全的聚合维度,不包含敏感数据。
可以在指标中使用 Exemplar,将某个延迟样本关联到 Trace ID。排障人员从 P99 曲线上的异常点直接打开代表性链路,减少先查日志再手工拼接时间范围的步骤。
五、理解指标基数
时间序列数量近似为标签取值组合的乘积。例如:
服务 40 × 路由 80 × 状态码 6 × 区域 3 × 实例 20
= 1,152,000 条潜在时间序列
如果再加入用户 ID 或完整 URL,数量会失控。治理方法包括:
- 路由使用模板
/orders/{id},不使用实际路径; - 状态码按类别或有限值记录;
- 删除不用于告警、分析和容量的标签;
- 在 Collector 中过滤或转换属性;
- 为团队设置基数预算和新增标签评审;
- 监控每个服务产生的序列数和遥测费用。
六、采样不是随机丢数据
头部采样
请求开始时决定是否采集,成本低、实现简单,但无法预知请求最后是否失败或很慢。
尾部采样
收集完整链路后再根据结果决定保留,可以优先保存错误、高延迟和特定业务,但需要缓冲、状态和更多 Collector 资源。
常见策略:
100% 保留错误链路
100% 保留超过 2 秒的链路
保留关键支付与登录链路
普通成功请求按 1%~10% 采样
为低流量服务设置最低样本保障
采样策略必须与 SLO 和事故调查需求一致。入口与下游应传播同一个采样决定,避免出现残缺链路。
七、设计 Collector 管道
典型管道包括 receiver、processor 和 exporter:
receivers:
otlp:
protocols:
grpc: {}
http: {}
processors:
memory_limiter: {}
batch: {}
attributes/redact: {}
exporters:
otlp/backend: {}
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, attributes/redact, batch]
exporters: [otlp/backend]
这是结构示意,不是可直接复制的生产配置。应补充认证、TLS、队列、重试、超时、内存上限和自身监控。Collector 本身故障不能阻塞应用主请求路径。
八、遥测管道的可靠性
监控以下内部指标:
- 接收、拒绝、丢弃和导出数据量;
- exporter 失败、重试和队列长度;
- 内存限制器触发次数;
- 批处理大小与导出延迟;
- 后端限流和配额;
- 配置加载、证书和认证失败;
- Collector CPU、内存和重启次数。
网络中断时无界缓存会耗尽磁盘或内存。应明确可接受的数据损失、队列上限和降级行为。
九、持续剖析解决什么
持续剖析周期性采样运行中的调用栈,可分析:
- On-CPU:哪些函数真正消耗 CPU;
- Off-CPU:线程在哪里等待锁、I/O 或调度;
- Heap:哪些调用路径持有内存;
- Allocations:哪些代码持续产生大量分配;
- Mutex/Lock:竞争发生在哪些调用路径。
相比临时登录服务器运行 profiler,持续剖析可以对比发布前后和异常前后。生产启用前必须测量采集开销,并限制访问权限,因为函数名、路径和标签可能暴露内部实现。
十、一次跨信号排障案例
现象:订单 API P99 在发布后从 280 ms 升到 1.8 s,但平均 CPU 只增加 8%。
- SLO 告警指出影响集中在
service.version=2.4.1; - Exemplar 打开一条慢 Trace,显示库存 RPC 等待时间正常,订单服务本地 Span 变慢;
- 关联日志没有外部错误,但出现连接池等待字段;
- Off-CPU Profile 显示大量线程等待同一互斥锁;
- 对比版本发现新缓存使用全局锁;
- 回滚后 P99 和锁等待恢复;
- 修复为分片锁,并增加锁等待剖析和回归压测。
这条证据链避免了“CPU 不高所以资源正常”的误判。
十一、成本治理
遥测成本来自采集、网络、处理、索引、存储和查询。优化顺序应是:
- 删除无用途数据和敏感字段;
- 控制指标标签基数;
- 按风险设计 Trace 采样;
- 为不同日志设置不同保留周期;
- 将原始明细和聚合数据分层存储;
- 按团队、服务和信号展示成本;
- 优化前确认不会破坏告警、审计与事故调查。
不能为了降成本把所有错误链路和安全日志一起丢弃。治理必须有数据所有者和例外审批。
十二、遥测数据安全
- 采集前进行字段分类和最小化;
- 通过 mTLS 或受控网络传输;
- Collector 和后端使用最小权限;
- 生产、测试和不同租户隔离;
- 查询、导出和删除操作留有审计;
- 对账号、地址和业务字段实施脱敏或哈希;
- 设定保留期限和删除验证;
- 禁止把秘密值放入资源属性、日志和 Span。
十三、可观测性成熟度
| 阶段 | 特征 | 下一步 |
|---|---|---|
| 1. 分散 | 各系统独立日志和监控 | 统一服务身份和时间 |
| 2. 集中 | 数据集中但不能关联 | 注入 Trace ID 与版本属性 |
| 3. 关联 | 指标、日志和链路互跳 | SLO、Exemplar 与尾部采样 |
| 4. 主动 | 发布对比、异常检测和容量预测 | 持续剖析与成本治理 |
| 5. 治理 | 数据质量、安全和费用可衡量 | 自动策略与持续改进 |
十四、常见错误
- 所有字段都转成指标标签;
- Trace 采样比例统一,错误请求也被随机丢弃;
- Collector 没有自身告警,数据中断很久才发现;
- 日志时间、时区和服务身份不一致;
- 只建设大屏,没有对应用户 SLO 和处置流程;
- Profile 长期开启却从不评估开销和权限;
- 采集敏感请求正文,希望后续再清理;
- 遥测费用无法归属到团队和服务。
十五、落地检查清单
- [ ] 服务名、版本、环境和实例属性跨信号一致;
- [ ] 日志包含 Trace ID,链路可以跳转日志;
- [ ] 指标标签经过基数评审;
- [ ] 采样优先保留错误、慢请求和关键业务;
- [ ] Collector 有限流、队列、重试和自身监控;
- [ ] 告警附带相关 Dashboard、Trace 和 Runbook;
- [ ] Profiles 开销、访问权限和保留策略已验证;
- [ ] 遥测数据经过脱敏、权限和生命周期治理;
- [ ] 每个信号都有明确使用者和成本归属。