排查 Collector 与 SDK 的问题
当遥测数据没有到达时的系统化检查清单:debug exporter、健康检查、内部指标和常见错误。
“我看不到我的数据”是最常见的 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 的内部指标放在一个仪表板上,这样下一次事故就能从证据开始。
热门指南
-
OpenTelemetry 详解:SDK、OTLP 与 Collector 在编写任何 YAML 之前,先了解各个活动部件以及配置所在的三个位置。 -
Collector 配置模型:组件、管线与 Provider 了解 Collector YAML 的规则:命名、管线、connector、合并文件和环境变量。 -
使用 OTEL_* 环境变量配置 SDK 使用标准变量为任何语言设置服务名称、exporter、采样和限制。 -
无需修改代码即可为应用插桩:Java、Python 和 Node.js 仅通过环境变量和命令行参数附加 OpenTelemetry agent。 -
让 Collector 达到生产就绪:内存限制、批处理与重试 配置 processor、队列和持久化存储,使遥测数据在过载和故障中存活。 -
使用 Helm 在 Kubernetes 上部署 Collector 安装官方 chart,使用 preset 处理日志和指标,并通过 values 文件覆盖配置。