4、必选Tag清单(上):span.kind、service.name、operation.name的定义与使用场景
在 Jaeger 的 Span 标签体系中,必选 Tag 是构成一条可观测数据的最小骨架。缺少其中任何一个,链路都无法被正确索引、聚合或展示。本章聚焦三个最核心的必选标签:span.kind、service.name 与 operation.name,深入剖析其定义、取值规范及典型使用场景。
4.1 三标签全景:链路数据的“身份证”
这三个标签共同决定了 Span 在分布式追踪中的“身份”与“位置”:
| 标签名 | 语义 | 作用域 | 是否可空 |
|---|---|---|---|
span.kind |
Span 的角色类型(客户端/服务端/内部等) | 单个 Span | 否 |
service.name |
产生该 Span 的微服务名称 | 进程级(通常由 Tracer 自动注入) | 否 |
operation.name |
Span 代表的具体操作(如 HTTP 路由、RPC 方法) | 单个 Span | 否 |
规范要点: 这三个标签必须在 Span 创建时立即赋值,不允许延迟注入或留空。Jaeger UI 的“服务”下拉框、拓扑图节点、Trace 列表页均依赖
service.name 进行聚合。
4.2 span.kind:定义 Span 的通信角色
span.kind 描述了 Span 在分布式调用中所扮演的通信角色。OpenTelemetry 规范定义了以下五种取值:
- CLIENT — 发起请求的一方(如 HTTP 客户端、gRPC 调用方)
- SERVER — 接收请求并处理的一方(如 HTTP 服务端、gRPC 处理器)
- PRODUCER — 消息队列中的生产者(如 Kafka 发布者)
- CONSUMER — 消息队列中的消费者(如 Kafka 订阅者)
- INTERNAL — 内部操作,不涉及跨进程通信(如本地函数调用、定时任务)
以下 SVG 展示了在一次典型 HTTP 调用中,span.kind 如何标识不同角色的 Span:
避坑指南: 不要将
span.kind 设置为 CLIENT 或 SERVER 后却未实现对应的网络传播上下文。例如,一个标记为 SERVER 的 Span 必须从上游提取 traceparent 或 uber-trace-id,否则链路将断裂。
4.3 service.name:微服务的“身份证号”
service.name 是 Jaeger 数据模型中最高层级的聚合键。它通常由 Tracer 初始化时通过 --jaeger-agent 参数或环境变量 JAEGER_SERVICE_NAME 注入,不应在单个 Span 中手动覆盖。
| 注入方式 | 示例 | 优先级 |
|---|---|---|
| 环境变量 | JAEGER_SERVICE_NAME=order-service |
最高 |
| 代码配置 | new Configuration("order-service") |
中 |
| 启动参数 | --jaeger.service.name=order-service |
低 |
命名规范: 使用小写字母 + 连字符(kebab-case),如
payment-api、user-srv。禁止包含空格、下划线或中文,否则 Jaeger UI 的拓扑图可能出现乱码或聚合异常。
4.4 operation.name:Span 的“操作名片”
operation.name 描述 Span 代表的具体操作。它必须具有可读性和可聚合性,通常采用 HTTP_METHOD /path 或 RPC_SERVICE/METHOD 的格式。
以下表格对比了好的与差的 operation.name 命名:
| 场景 | 差的命名 | 好的命名 | 原因 |
|---|---|---|---|
| HTTP GET 订单 | /api/v1/orders/12345 |
GET /api/v1/orders/{id} |
包含具体 ID 会导致每个请求生成唯一 operation.name,无法聚合 |
| gRPC 调用 | GetUserProfile |
user.UserService/GetProfile |
应包含包名和服务名,避免不同服务间方法名冲突 |
| 数据库查询 | SELECT * FROM orders WHERE id=? |
DB.Orders.SelectById |
避免暴露完整 SQL,使用语义化简写 |
4.5 三标签协同:构建可搜索的 Trace 骨架
当三个标签正确赋值后,Jaeger 后端可以高效地完成以下操作:
- 服务拓扑构建 — 通过
service.name聚合节点,span.kind判断调用方向。 - 操作维度分析 — 在“服务”页面下,按
operation.name展示延迟、错误率、吞吐量。 - 链路搜索 — 用户可在 Jaeger UI 中按
service.name+operation.name组合过滤 Trace。
以下 SVG 展示了这三个标签在 Jaeger 数据模型中的协作关系:
生产建议: 在微服务框架(如 Spring Boot、Go kit)的中间件中自动注入
span.kind 和 operation.name,避免业务开发人员手动设置。例如,HTTP 框架拦截器可根据请求方法和路由模板自动生成 GET /api/v1/orders/{id}。
4.6 常见错误与排查
| 错误现象 | 根因 | 修复方案 |
|---|---|---|
| Jaeger UI 服务列表为空 | service.name 未设置或为空字符串 |
检查 Tracer 初始化配置,确保 JAEGER_SERVICE_NAME 已设置 |
| Trace 中 Span 显示为“未知操作” | operation.name 未赋值或为 null |
在创建 Span 时显式调用 setOperationName() |
| 拓扑图连线方向错误 | span.kind 被错误设置为 CLIENT 或 SERVER |
根据实际调用方向修正 span.kind,客户端为 CLIENT,服务端为 SERVER |
| 同一操作产生大量不同 operation.name | 使用了带具体参数的 URL 路径 | 使用路由模板替换具体 ID,如 /orders/{id} |
复盘检查清单:
- 每个 Span 是否都包含
span.kind? service.name是否在进程级别全局唯一且稳定?operation.name是否使用模板而非具体值?- 跨进程调用中,CLIENT 与 SERVER 的
span.kind是否成对出现?