Collector と SDK のトラブルシューティング
テレメトリが届かないときの体系的なチェックリスト:debug exporter、ヘルスチェック、内部メトリクス、よくある間違い。
「データが見えない」は、OpenTelemetry で最も一般的な問題であり、その原因はほとんどの場合、設定ミスの短いリストのうちの 1 つです。アプリケーションから外側へ、一度に 1 ホップずつ作業し、次に進む前に、各ホップを証明してください。
アプリの SDK ──▶ Collector の receiver ──▶ processors ──▶ exporter ──▶ バックエンド
1 2 3 4 5
ステップ 0:設定を検証する
otelcol-contrib validate --config=config.yaml
これは、YAML のエラー、不明なコンポーネント名、不正なオプション名、定義されていないコンポーネントを参照するパイプラインを検出します。ディストリビューションに合うバイナリ名(otelcol、otelcol-contrib、otelcol-k8s)を使ってください。コンテナでは、デプロイと同じイメージとマウントした設定で実行します。
ステップ 1:SDK は送信しているか
SDK の診断とコンソール exporter を有効にして、「アプリが何も生成しなかった」と「生成したが届かなかった」を切り分けます。
export OTEL_LOG_LEVEL=debug
export OTEL_TRACES_EXPORTER=console # または "logging"。言語によって異なる
一般的な原因を確認します。
- エンドポイントとプロトコルが一致していない。
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 のシャットダウンやフラッシュを呼び出します。
ステップ 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ではなく、otlp/tempo)。 - シグナルのタイプが一致していること:
tracesのパイプラインは、トレースをサポートしない receiver や exporter を使えません。 - extension が
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 のログを読みます。そこにスパンが見えれば、receiver と processor が機能していることが分かるので、問題は後段にあります。何も見えない場合は、データがパイプラインに届かなかったか、processor が破棄したかです(filter の processor や tail サンプラーが、よくある容疑者です)。完了したら、debug を削除するか、詳細度を下げてください。すべての項目をログに記録するからです。
ステップ 5:Collector 自身のシグナルを使う
ヘルスチェック:
extensions:
health_check:
endpoint: 0.0.0.0:13133
service:
extensions: [health_check]
curl http://collector:13133/ がステータスを返します。Kubernetes の liveness と readiness の probe に使います。
内部メトリクスは、デフォルトでポート 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:トークンやヘッダーがないか、間違っています。未設定の${env:VAR}は空の値になるため、変数が Pod で設定されていることを確認します(kubectl exec ... -- env)。415やパースのエラー:プロトコルの不一致。たとえば、otlp(gRPC)を HTTP のポートに向けている。- HTTP での
404:バックエンドが期待するベースのパスを確認します(Loki は/otlp、Prometheus は/api/v1/otlp)。 - Prometheus が OTLP を拒否する:その OTLP receiver の feature flag が有効になっていません。
自動計装のチェック
Operator ベースの注入では、Instrumentation が Pod の起動前に存在したこと、アノテーションが Pod テンプレートにあること、アプリケーションの Pod に opentelemetry-auto-instrumentation という init コンテナがあることを確認します。リソースを作成または変更した後は、ワークロードを再起動します。エージェントベースの構成では、エージェントのフラグや環境変数が実際に適用されていることを確認します(-javaagent:、opentelemetry-instrument、--require)。
クイックリファレンス
| 症状 | 最初に確認すること |
|---|---|
| Collector のログに何もない | SDK のエンドポイント、プロトコル、ポート。コンテナ内の localhost |
| Collector はデータを受信するが、バックエンドは受信しない | パイプライン内の exporter、エンドポイント、認証、プロトコル |
| Collector が起動しない | validate の出力。イメージにないコンポーネント |
データが unknown_service として表示される | OTEL_SERVICE_NAME を設定する |
| メモリの増加や再起動 | memory_limiter を最初に、キューのサイズ、リソースの制限 |
| サンプリング後の部分的なトレース | 1 つのトレースは 1 つの Collector に届く必要がある(ロードバランシングの層) |
| 一部のデータが断続的に欠落する | キューがいっぱい、またはリトライの上限に達した。send_failed とキューのメトリクスを確認 |
一度に 1 ホップずつ修正し、作業中は debug exporter を手元に置き、次のインシデントが証拠から始まるように、Collector の内部メトリクスをダッシュボードに載せてください。
人気のガイド
-
OpenTelemetry を解説する:SDK、OTLP、Collector YAML を 1 行も書く前に、構成要素と、設定が存在する 3 つの場所を理解します。 -
Collector の設定モデル:コンポーネント、パイプライン、プロバイダー Collector の YAML のルールを学びます。命名、パイプライン、connector、ファイルのマージ、環境変数。 -
OTEL_* 環境変数で SDK を設定する 標準の変数を使って、任意の言語のサービス名、exporter、サンプリング、制限を設定します。 -
コードを変更せずにアプリを計装する:Java、Python、Node.js 環境変数とコマンドラインのフラグだけで、OpenTelemetry のエージェントをアタッチします。 -
Collector を本番対応にする:メモリ制限、バッチ処理、リトライ 過負荷や障害の間もテレメトリが生き残るように、processor、キュー、永続ストレージを設定します。 -
Helm で Kubernetes に Collector をデプロイする 公式チャートをインストールし、ログとメトリクスに preset を使い、values ファイルで設定を上書きします。