用 OpenTelemetry Collector tail_sampling 只保留错误或慢请求的 trace
用 OpenTelemetry Collector tail_sampling 只保留错误或慢请求的 trace
问题场景
在微服务架构中,OpenTelemetry 可以采集完整的调用链。全量上报 trace 会给追踪后端带来巨大的存储和索引压力。实际上,大部分正常且快速的请求在排查问题时价值有限,真正需要长期保留的是错误请求和慢请求。如果能在 Collector 侧完成筛选,只把错误或慢请求的 trace 发给后端,就能显著降低存储成本。
OpenTelemetry Collector 的 tail_sampling processor 支持在收到完整 trace 后再做采样决策,因此可以基于 trace 的最终状态(例如是否包含错误、总耗时是否超阈值)决定保留或丢弃。
配置思路
tail_sampling 的核心是“先缓存、后决策”。Collector 会等待一段时间(decision_wait),让同一 trace 的 span 尽量到齐,然后按策略判断。对于“只保留错误或慢请求”的需求,可以配置两个策略:
- status_code 策略:只要 trace 中任一 span 的状态码为 ERROR,就保留。
- latency 策略:只要 trace 的总耗时超过阈值(例如 500ms),就保留。
多个策略之间是“或”的关系,任一命中即保留。没有命中任何策略的 trace 会被丢弃,从而实现只保留错误或慢请求。
最小可运行示例
下面是一个 Collector 配置示例,用于接收 OTLP 数据,开启 tail_sampling,并将采样后的 trace 输出到日志(便于本地验证)。实际使用时,把 exporter 换成后端地址即可。
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
tail_sampling:
# 等待 trace 完整的时间,需大于业务最长链路耗时
decision_wait: 30s
# 缓存 trace 数量,根据流量调整
num_traces: 50000
# 预期每秒新 trace 数,帮助分配缓存
expected_new_traces_per_sec: 100
policies:
- name: errors-policy
type: status_code
status_code:
status_codes: [ERROR]
- name: slow-policy
type: latency
latency:
threshold_ms: 500
exporters:
# 本地验证用 logging;生产环境替换为 OTLP 或 APM 后端
logging:
verbosity: detailed
service:
pipelines:
traces:
receivers: [otlp]
processors: [tail_sampling]
exporters: [logging]
说明:
- decision_wait:默认 30s,表示 Collector 收到首个 span 后等待多久做决策。如果业务链路最长可能超过 30s,需要调大,否则慢请求可能在决策后才结束,导致漏采。
- num_traces:缓存中最多保留的 trace 数。根据 QPS 和 decision_wait 估算,避免内存过高。
- expected_new_traces_per_sec:预估每秒新 trace 数,有助于内部缓存分配,可按实际流量填写。
- status_code 策略:status_codes 列出需要保留的状态码,这里保留 ERROR。
- latency 策略:threshold_ms 为总耗时阈值,单位毫秒,示例为 500ms。
运行方法
可以使用官方 Collector contrib 镜像运行上面的配置。假设配置文件名为 config.yaml,放在当前目录:
docker run --rm \
-p 4317:4317 \
-p 4318:4318 \
-v $(pwd)/config.yaml:/etc/otelcol/config.yaml \
otel/opentelemetry-collector-contrib:<版本>
请将 <版本> 替换为实际使用的镜像标签,例如 0.100.0 或更高兼容版本。运行后,Collector 会监听 4317(gRPC)和 4318(HTTP)。
接下来让应用通过 OTLP 发送 trace。如果已有 OpenTelemetry SDK,将 OTLP exporter 指向 http://localhost:4318 或 localhost:4317 即可。也可以使用 telemetrygen 等测试工具生成模拟 trace:
telemetrygen traces --otlp-endpoint localhost:4317 --otlp-insecure --duration 10s
然后观察 Collector 日志,只有包含 ERROR 状态或耗时超过 500ms 的 trace 会被输出。正常且快速的 trace 不会出现在日志中。
边界与限制
-
decision_wait 与慢请求的完整性 decision_wait 必须大于业务链路的最长耗时。如果某个慢请求的总耗时超过 decision_wait,Collector 可能在它结束前就做出丢弃决策。建议先统计 P99 或最大链路耗时,再设置一个留有余量的值。
-
内存占用 tail_sampling 需要把 trace 缓存在内存中。num_traces 和 decision_wait 越大,内存占用越高。高流量场景下应结合 expected_new_traces_per_sec 和实际内存监控逐步调整,避免 OOM。
-
多 Collector 实例的负载均衡 如果部署了多个 Collector 实例,同一个 trace 的 span 可能被发送到不同实例。每个实例只看到部分 span,可能无法正确判断错误或总耗时。此时需要保证同一 trace_id 始终路由到同一个 Collector,例如在 Collector 前使用按 trace_id 的负载均衡,或使用支持一致性哈希的网关。最简单的做法是单实例部署,或让应用侧只指向一个 Collector。
-
状态码依赖应用正确设置 status_code 策略依赖 span 的 status 字段。应用需要在捕获异常时显式将 span 状态设为 ERROR,否则错误请求可能不会被识别。
-
策略匹配与丢弃 多个策略是“或”关系。没有匹配任何策略的 trace 会被丢弃。这符合“只保留错误或慢请求”的目标,但也意味着正常请求的 trace 不会进入后端,排查非错误类问题时需要临时调整策略或开启兜底采样。
-
版本兼容性 OpenTelemetry Collector 的配置字段可能随版本变化。本文示例基于 tail_sampling processor 的通用配置,实际部署时请以所用版本的官方文档为准。
小结
通过 tail_sampling 的 status_code 和 latency 策略,可以在 Collector 侧只保留错误或慢请求的 trace,减少追踪后端存储成本。关键是合理设置 decision_wait,确保慢请求在决策前已经完整到达;同时注意内存限制、多实例路由和状态码上报质量。对于已经使用华为云 APM 或类似可观测后端的团队,可以将 exporter 指向对应 OTLP 接入点,让后端只接收高价值 trace。
- 点赞
- 收藏
- 关注作者
评论(0)