LabHub
学习 学习路径 课程

OTCA — OpenTelemetry 认证助理

自动埋点给你的只有一条网络边界

在 LabHub 中继续学习

一句话总结

启用自动计量,准确得到的只有一个东西:网络边界。HTTP 服务端与客户端、gRPC、DB 驱动、Redis 和消息队列客户端会产生 span;进程内部工作不会表现为任何 span,只会成为父 span 的 self time 空白。

概念图: 网络边界 · self time · 第 3 步先于第 4 步 · 哪里不是问题

为什么需要它

计量失败的团队几乎都以同样方式失败:先在代码里埋手工 span,两周后有 300 个 span,追踪却仍在服务边界断裂。有效顺序是固定的。

顺序 要做的事 跳过后的结果
1 启用自动计量并确认数据到达 后续所有调试都靠猜测
2 确定资源属性 日后修改会与历史数据断开
3 验证跨服务传播 增加 span 也只会得到碎片
4 只在 self time 大的区间添加手工 span 自动计量的空白永远存在
5 把处理与采样迁移到 Collector 每次改策略都要重新部署所有服务

关键是第 3 步先于第 4 步。传播已断时增加手工 span,只会把破碎追踪切得更碎。

工作原理

启用自动计量后会得到这样的追踪。

SERVER    checkout-api   POST /v1/orders                       1421ms
├─ CLIENT    GET http://auth.internal/verify                      31ms
├─ CLIENT    SELECT carts WHERE id = ?                             6ms
├─ CLIENT    redis GET promo:rules:t-8871                          2ms
├─ CLIENT    POST http://payment.internal/charge                  74ms
└─ (나머지 1308ms 는 어떤 스팬에도 속하지 않음)

最后一行就是全部线索。自动计量用 1,308ms 的空白告诉我们哪里不是问题。这段空白是 self time,手工 span 只应加在这里。

自动计量绝对看不到:进程内 CPU 工作(序列化、压缩、模板渲染、加密)、锁与连接池等待、GIL 竞争和事件循环延迟、没有计量包的第三方 SDK 调用,以及业务逻辑分支。

手工 span 应放在五处

  1. 循环和批处理边界——把迭代次数记为属性
  2. 缓存查询——记录是否命中,可直接观察缓存效率
  3. 没有计量包的第三方 SDK 调用
  4. 锁、队列、连接池等待
  5. 长时间占用 CPU 的区间——序列化、压缩、生成报告

加入后,空白会这样被填充。

├─ INTERNAL  checkout.apply_promotions                          1298ms
│  ├─ INTERNAL  promotion.load_rules   cache.hit=false           1241ms  <-- 여기
│  └─ INTERNAL  promotion.evaluate     evaluated=812               54ms

只需遵守一条span 命名规则:名称必须低基数。不应写 GET /v1/orders/A-99183,而应写 GET /v1/orders/:id;具体值全部作为属性。后端按 span 名称分组生成延迟统计和服务图,名称含 ID 会摧毁整个聚合视图。

资源属性以后无法修复。 与 span 属性不同,资源属性附在进程输出的所有信号上;修改 service.name 会断开仪表板、告警、服务图和历史数据。

属性 示例 能否修改
service.name checkout-api 实际上不能
service.namespace commerce 很困难
service.version 2.7.1 每次部署变化
deployment.environment.name prod 不能
service.instance.id Pod 名称 每次重启变化

常见错误有两个。第一,环境属性名是 deployment.environment.name;旧名 deployment.environment 已不再使用。名称不同会形成两个独立属性,仪表板变量只会读取其中一个。第二,service.name 表示服务单位,不是部署单位。把 canary 命名为 checkout-api-canary,会在服务图中产生幽灵节点。

采样器建议从 parentbased_always_on 开始。如果一开始就启用比例采样,看不到追踪时无法区分是计量问题还是采样导致。切换到比例后也必须使用 parentbased_traceidratio。若不遵循父级决定、各服务独立随机判断,追踪会在中间断裂。

现场会遇到的情况

计量破坏应用的方式反复出现。

症状 原因 应对
部署后内存持续增长 后端延迟导致 exporter 队列塞满 明确队列上限,改为经过 Collector
只到达部分 span 退出时未 flush 调用 shutdown,延长终止宽限期
单个 span 数百 KB 把完整请求正文放入属性 设置属性值长度上限
服务图出现幽灵节点 canary 使用单独 service.name service.name 按服务固定

SDK 默认没有属性值长度上限。属性数量默认限制为 128,但值长度无限,因此完整请求正文进入后,传输与存储成本会完整跟随。显式设置上限更安全。

下一实验要做什么

/root/otca-sdk/ 下编写 SDK 环境变量文件,按约定设置资源属性,并创建使用 Kubernetes Downward API 注入 Pod 名称和命名空间的 Deployment,实际应用。最后整理 span 名称列表,并亲自编写捕获名称中 ID 的 linter。