OpenTelemetry OpenTelemetry

排查 Collector 与 SDK 的问题

当遥测数据没有到达时的系统化检查清单:debug exporter、健康检查、内部指标和常见错误。

12 min 中级

“我看不到我的数据”是最常见的 OpenTelemetry 问题,而原因几乎总是一小串配置错误中的一个。从应用向外逐跳排查,在进入下一跳之前先证明每一跳。

App SDK ──▶ Collector receiver ──▶ processors ──▶ exporter ──▶ Backend
   1              2                    3              4            5

第 0 步:验证配置

otelcol-contrib validate --config=config.yaml

这能捕获 YAML 错误、未知的组件名称、错误的选项名称,以及引用了未定义组件的管线。请使用与你的发行版相匹配的二进制名称(otelcol、otelcol-contrib、otelcol-k8s)。在容器中,请使用与你的部署相同的镜像和挂载的配置来运行它。

第 1 步:SDK 在发送吗?

启用 SDK 诊断和 console exporter,以区分”应用什么都没产生”和”应用产生了但没有到达”:

export OTEL_LOG_LEVEL=debug
export OTEL_TRACES_EXPORTER=console   # or "logging", depending on the language

检查常见原因:

  • 端点和协议不匹配。 OTEL_EXPORTER_OTLP_PROTOCOL 必须与端口匹配:grpc 发往 4317,http/protobuf 发往 4318。把 HTTP 发送到 gRPC 端口,或者反过来,会失败,并出现看起来像连接或解析问题的错误。
  • HTTP 的路径错误。 OTEL_EXPORTER_OTLP_ENDPOINT 是一个基础 URL;SDK 会添加 /v1/traces。特定于信号的变量,比如 OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,是按给定的原样使用的,所以它们必须包含完整路径。
  • 容器内的 localhost。 应用的 localhost 就是应用自己。请使用 Collector 的 Service 或容器名称。
  • SDK 被禁用,或者 exporter 是 none。 查找 OTEL_SDK_DISABLED=true 或 OTEL_TRACES_EXPORTER=none。
  • 没有 service.name。 数据被接受,但显示为 unknown_service,看起来像是缺失了数据。请设置 OTEL_SERVICE_NAME。
  • 短生命周期的进程在导出之前就退出了。 批处理 exporter 是周期性发送的,所以请在退出前调用 SDK 的 shutdown 或 flush。

第 2 步:receiver 可达吗?

curl -i http://collector:4318/v1/traces \
  -H 'Content-Type: application/json' -d '{}'

HTTP 200 响应(空的 JSON 主体就可以)表明 HTTP receiver 可达。对于 gRPC,grpcurl 之类的工具或 TCP 检查(nc -zv collector 4317)能证明端口是开放的。如果不是:

  • receiver 可能被绑定到了 localhost。请显式设置 endpoint: 0.0.0.0:4317。
  • Kubernetes Service 可能没有暴露该端口,或者 pod 的 containerPort 缺失。
  • NetworkPolicy、防火墙或服务网格可能阻止了流量。

第 3 步:管线连好了吗?

这是最常见的 Collector 错误:组件已定义但没有被使用。 定义 exporters.otlp/tempo 不会有任何作用,直到它出现在 service.pipelines.<signal>.exporters 中。receiver、processor、extension 和 connector 也是如此。

检查:

  • 组件在管线中的名称与它的定义完全一致,包括任何后缀(是 otlp/tempo,而不是 otlp)。
  • 信号类型匹配:traces 管线不能使用不支持追踪的 receiver 或 exporter。
  • 扩展被列在 service.extensions 下。
  • 在 Helm values 中,请记住列表是替换,所以你部分重新定义的管线可能丢失了默认组件。

第 4 步:在 Collector 内部查看数据

将 debug exporter 添加到管线:

exporters:
  debug:
    verbosity: detailed

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [debug, otlp/tempo]

读取 Collector 的日志。在那里看到 span 证明 receiver 和 processor 在工作,所以问题出在下游。什么都没看到意味着数据从未到达管线,或者某个 processor 把它丢弃了(filter processor 或尾部采样器是通常的嫌疑)。完成后请移除 debug 或降低它的详细程度,因为它会记录每一个条目。

第 5 步:使用 Collector 自己的信号

健康检查:

extensions:
  health_check:
    endpoint: 0.0.0.0:13133
service:
  extensions: [health_check]

curl http://collector:13133/ 返回一个状态。把它用于 Kubernetes 的存活和就绪探针。

内部指标默认在 8888 端口提供(请查看你所用版本的 service.telemetry.metrics):

curl -s http://collector:8888/metrics | grep -E 'otelcol_(receiver|processor|exporter)_'

把它们当作一个漏斗来读:

指标家族含义
otelcol_receiver_accepted_*成功接收的条目
otelcol_receiver_refused_*被拒绝,通常是被 memory_limiter
otelcol_processor_dropped_*被某个 processor 丢弃
otelcol_exporter_sent_*已交付到后端
otelcol_exporter_send_failed_*后端拒绝或不可达
otelcol_exporter_queue_size 和 _capacity队列深度及其上限

accepted 计数上升而 sent 计数持平,告诉你问题出在 exporter。refused 计数指向内存限制。指标名称在不同版本之间有所调整,所以请查看 Collector 的内部遥测文档了解你的版本。

zPages 提供管线和最近追踪的实时视图:

extensions:
  zpages:
    endpoint: localhost:55679

浏览 /debug/tracez 和 /debug/pipelinez(在集群上通过 kubectl port-forward)。请让它保持绑定在 localhost。

第 6 步:后端接受它吗?

查看 Collector 日志中的 exporter 错误:

  • connection refused 或 deadline exceeded:端点、端口错误,或网络被阻止。
  • certificate signed by unknown authority:添加 tls.ca_file,或修正端点使其使用正确的主机名。
  • 401 或 403:令牌或头部缺失或错误。请确认环境变量已在 pod 中设置(kubectl exec ... -- env),因为未设置的 ${env:VAR} 会变成空值。
  • 415 或解析错误:协议不匹配,比如把 otlp(gRPC)指向了 HTTP 端口。
  • HTTP 上的 404:检查后端期望的基础路径(Loki 使用 /otlp,Prometheus 使用 /api/v1/otlp)。
  • Prometheus 拒绝 OTLP:它的 OTLP receiver 功能标志没有启用。

自动插桩检查

对于基于 Operator 的注入,请确认 Instrumentation 在 pod 启动之前就已存在,注解位于 pod 模板上,并且应用 pod 拥有 init 容器 opentelemetry-auto-instrumentation。在创建或更改该资源之后重启工作负载。对于基于 agent 的设置,请确认 agent 的标志或环境变量确实已被应用(-javaagent:、opentelemetry-instrument、--require)。

快速参考

症状首先检查
Collector 日志中什么都没有SDK 端点、协议、端口;容器中的 localhost
Collector 收到数据,后端没有管线中的 exporter;端点;认证;协议
Collector 启动失败validate 的输出;镜像中缺少该组件
数据显示为 unknown_service设置 OTEL_SERVICE_NAME
内存增长或重启memory_limiter 在最前、队列大小、资源限制
采样后出现不完整的追踪一条追踪必须到达同一个 Collector(负载均衡层)
部分数据间歇性缺失队列已满或达到重试上限;检查 send_failed 和队列指标

一次修复一跳,在工作时手边保留 debug exporter,并把 Collector 的内部指标放在一个仪表板上,这样下一次事故就能从证据开始。

热门指南