在分布式架构与微服务体系中,将 Tracing(链路)、Metrics(指标)、Logs(日志)三种遥测数据有机构建为"三位一体" (3D Observability) 的可观测性网络,是保障系统高可用性的基石。
以下是针对这三类遥测数据定义的生产级落地规范指南,遵循 2026 年 OpenTelemetry 最新语义规范(Semantic Conventions),旨在实现高内聚、低耦合以及强可关联性。
一、 Tracing(分布式链路追踪)规范
Tracing 的核心目标是还原请求拓扑与耗时上下文。生产环境严禁滥用自定义字符串作为属性名,必须遵循 OTel 属性命名空间约束。
1.1 Span 命名与状态规范
-
Span Name 强制约束:必须是低基数(Low Cardinality)的静态字符串。
-
HTTP 路由 :统一使用
{http.request.method} {http.route},例如GET /api/v1/users/:id。严禁包含动态 ID(如GET /api/v1/users/123)。 -
RPC/Service 方法 :统一使用
{packageName}.{className}/{methodName}。 -
DB 操作 :统一使用
{db.operation} {db.collection.name},例如SELECT users。 -
Span Status 规范:
-
Unset (默认):表示执行正常。
-
Error :仅在业务逻辑真正失败、触发降级或抛出未捕获异常时触发。对应的 HTTP 状态码为
5xx。对于业务预期的4xx(如参数校验失败、密码错误),Span Status 保持Unset,通过 Attributes 记录错误码。
1.2 语义属性(Attributes)分类定义标准
根据 2026 OTel 最新规范,废弃了旧版的 http.method 等平铺标签,全面采用层级命名空间:
| 命名空间 | 统一属性键 (Attribute Key) | 生产示例/合法值 | 说明 |
|---|---|---|---|
| HTTP | http.request.method |
http.response.status_code
url.path
client.address | POST
200
/api/v1/login
192.168.1.100 | 严禁在 url.path 中记录包含敏感 Token 的 Query 串 |
| DB | db.system
db.query.text
db.collection.name
db.response.affected_rows | mysql
SELECT * FROM users WHERE id = ?
users
1 | 生产环境严禁 在 db.query.text 中记录 Raw SQL 真实参数,必须参数化 |
| RPC | rpc.system
rpc.service
rpc.method | grpc
user.UserService
CreateUser | 用于微服务内部通信 |
| Business (自定义) | biz.tenant_id
biz.order.type
biz.error_code | tenant_10293
flash_sale
USER_NOT_FOUND | 业务自定义空间,严禁包含 PII(个人隐私数据如手机号、密码) |
1.3 Go 生产级埋点代码示例
go
package tracing
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/codes"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
"go.opentelemetry.io/otel/trace"
)
var tracer = otel.Tracer("com.yourcompany.app.order")
func ProcessOrder(ctx context.Context, orderID string, tenantID string) (err error) {
// 1. 创建符合语义规范的 Span
ctx, span := tracer.Start(ctx, "OrderService.ProcessOrder",
trace.WithSpanKind(trace.SpanKindInternal),
)
defer span.End()
// 2. 注入标准与自定义属性
span.SetAttributes(
semconv.StandardAttribute("biz.tenant_id", tenantID),
semconv.StandardAttribute("biz.order.id", orderID),
)
// 模拟业务执行失败
if err = doProcess(ctx); err != nil {
// 3. 生产规范:异常时必须记录 Error 状态、Error Event,并设置 Status
span.RecordError(err, trace.WithStackTrace(true))
span.SetStatus(codes.Error, "failed to process order in database")
return err
}
span.SetStatus(codes.Ok, "success")
return nil
}
二、 Metrics(指标)规范
Metrics 的核心目标是反映系统及业务的瞬时状态与趋势趋势 。生产治理的核心痛点是防止基数爆炸(Cardinality Explosion)。
1.1 类型选用与命名规范
-
命名格式 :统一采用
小写字母+下划线,格式为{namespace}.{component}.{noun}_{unit}。 -
正确示例 :
http.server.request.duration_milliseconds -
错误示例 :
Http_Server_ReqTime -
四大核心工具选用矩阵:
| 工具类型 (Instrument) | 适用场景 | 聚合行为 | 生产示例 |
|---|---|---|---|
| Counter (计数器) | 只增不减的累加值 | Rate(速率)、Sum(总数) | http.server.request.count |
| UpDownCounter | 可增可减的瞬时量 | Sum(当前存量) | k8s.pod.running.count |
| Gauge (仪表盘) | 剧烈波动的非累加瞬时值 | Last Value(最新值) | system.cpu.utilization |
| Histogram (直方图) | 耗时、大小分布(带分位数) | Percentiles (p95, p99), Bucket | db.client.query.duration_ms |
1.2 高基数(Cardinality)控制红线
警告:Metrics 的 Attributes 组合产生的唯一序列(TimeSeries)如果超过 10 万 级别,会导致 Prometheus/M3DB 等存储组件内存瘫痪。
- 允许作为指标 Label 的字段 :
http.request.method、http.response.status_code、rpc.service、deployment.environment。 - 绝对禁止作为指标 Label 的字段 :
user_id、order_id、phone_number、带有动态参数的url。 - 降级策略 :若业务必须统计 Top 活跃用户的请求量,应使用专门的日志分析(如 ELK/ClickHouse)或通过 Redis HyperLogLog 统计,严禁塞入 Metrics 标签。
1.3 现代度量核心:Exemplars(样本联动)
2026 年可观测性标配要求 Metrics 具备 Exemplars 能力。在采集 Histogram 指标(如耗时)时,自动附带一个当时触发该高耗时请求的 TraceID。当监控大盘上 p99 突刺时,运维人员可以直接点击波峰,跳转到具体 Trace 查看详情。
三、 Logs(日志)规范
Logs 的核心目标是提供详尽、离散的上下文转储 。生产环境坚决禁止打印无结构的纯文本日志(如 log.Infof("user %s login success", name))。
3.1 统一 JSON 结构化元数据标准
所有应用组件输出的日志必须满足以下标准化 JSON Schema:
json
{
"timestamp": "2026-05-21T12:00:00.123456Z",
"level": "ERROR",
"service.name": "backend-service",
"service.version": "v2.1.0",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"trace_flags": "01",
"logger": "com.yourcompany.auth.jwt",
"message": "Token verification failed: expired",
"error": {
"kind": "JwtExpiredError",
"stack": "github.com/your/package/auth.VerifyToken:34..."
},
"attributes": {
"biz.tenant_id": "tenant_10293",
"http.request.method": "POST"
}
}
3.2 日志级别(Level)生产执行阶梯
- DEBUG:本地与测试环境详细调试信息。生产环境默认关闭。
- INFO:核心状态机变更、关键业务生命周期(如:订单创建、支付成功)。
- WARN:业务低风险异常,系统有自动容错/重试机制(如:Redis 缓存穿透走 DB、单次 RPC 超时重试成功)。
- ERROR:单次请求彻底失败,需要人工介入介入或系统告警(如:数据库连接断开、第三方支付网关持续 502)。
- FATAL :不可逆的致命错误,触发进程崩溃退出(仅允许在
main.go初始化阶段使用)。
四、 跨数据源立体联动规范(Correlation)
要彻底消除可观测性孤岛,必须建立强关联。其核心桥梁是 TraceContext 与 Baggage。
┌────────────────────────┐
│ Metrics │
│ (带 TraceId Exemplar) │
└───────────┬────────────┘
│ 1. 发现指标异常
▼
┌──────────────┐ 2. 点击 Exemplar 跳转 ┌──────────────┐
│ Logs │◄────────────────────────────┤ Tracing │
│ (带 TraceId) │ 3. 过滤相同 TraceId │ (全链路拓扑) │
└──────────────┘ └──────────────┘
- Tracing →\rightarrow→ Logs 联动 :
在打印每一行日志时,底层日志框架(如 Go 的zap,SvelteKit 的winston)必须通过当前逻辑上下文Context自动提取TraceID和SpanID并作为 JSON 的一级字段输出。 - Metrics →\rightarrow→ Tracing 联动 :
利用 OTel Metric SDK 的WithExemplar动态关联。 - 全链路上下文透传 (Baggage) :
当需要跨服务追踪某些非核心链路线索时(如:判定某个请求是否为"压力测试流量"或属于哪个"商户等级"),利用 OTel Baggage 在 HTTP Header 中进行多级透传,后端所有 Trace、Log 自动解析并打上该标签:
baggage: is_stress_test=true,merchant_level=gold
五、 2026 生产落地性能保障治理
- 异步化与批量化 (Batching):
- Traces/Logs 必须采用
BatchSpanProcessor/BatchLogRecordProcessor。应用层先写入内存 RingBuffer,由后台线程每 5 秒或满 512 条异步刷新至 OpenTelemetry Collector。 - 严禁在业务主线程中发生同步网络 I/O 阻塞发送遥测数据。
- 动态采样(Tail-Based Sampling):
- Head-Based (前端采样):客户端或网关层设置固定采样率(如 10%)。
- Tail-Based (尾部采样 - 推荐) :应用层 100% 吐出数据到内网的 OpenTelemetry Collector,在 Collector 侧配置过滤策略:
- 若
http.response.status_code >= 500或包含error标签,100% 保留。 - 若响应时间
duration_ms > 2000(慢 SQL/慢接口),100% 保留。 - 普通的
HTTP 200成功请求,按 1% 比例等比抽样留存。
- 内存保护机制 (Resource Limiting) :
在部署 OpenTelemetry Collector 时,必须配置memory_limiter处理器。当 Collector 所在节点内存达到 80% 阈值时,自动触发丢弃(Drop)策略,优先丢弃低优先级的 Trace/Log,确保不可观测性组件本身不拖垮生产业务。