OpenTelemetry OpenTelemetry

Fehler bei Collector und SDKs beheben

Eine systematische Checkliste für den Fall, dass Telemetrie nicht ankommt: Debug-Exporter, Health Checks, interne Metriken und häufige Fehler.

12 min Fortgeschritten

„Ich sehe meine Daten nicht“ ist das häufigste OpenTelemetry-Problem, und die Ursache ist fast immer einer von wenigen Konfigurationsfehlern. Arbeite von der Anwendung nach außen, einen Hop nach dem anderen, und belege jeden Hop, bevor du zum nächsten weitergehst.

App-SDK ──▶ Collector-Receiver ──▶ Prozessoren ──▶ Exporter ──▶ Backend
   1              2                    3              4            5

Schritt 0: die Konfiguration validieren

otelcol-contrib validate --config=config.yaml

Das fängt YAML-Fehler, unbekannte Komponentennamen, falsche Optionsnamen und Pipelines ab, die nicht definierte Komponenten referenzieren. Nutze den Binary-Namen, der zu deiner Distribution passt (otelcol, otelcol-contrib, otelcol-k8s). In einem Container führe es mit demselben Image und der gemounteten Konfiguration wie dein Deployment aus.

Schritt 1: sendet das SDK?

Aktiviere SDK-Diagnose und einen Console-Exporter, um „die App hat nichts erzeugt“ von „die App hat es erzeugt, aber es kam nicht an“ zu trennen:

export OTEL_LOG_LEVEL=debug
export OTEL_TRACES_EXPORTER=console   # oder "logging", je nach Sprache

Prüfe die üblichen Ursachen:

  • Endpunkt und Protokoll passen nicht. OTEL_EXPORTER_OTLP_PROTOCOL muss zum Port passen: grpc geht an 4317, http/protobuf geht an 4318. HTTP an den gRPC-Port zu senden oder umgekehrt schlägt mit Fehlern fehl, die wie Verbindungs- oder Parsing-Probleme aussehen.
  • Falscher Pfad bei HTTP. OTEL_EXPORTER_OTLP_ENDPOINT ist eine Basis-URL; das SDK fügt /v1/traces hinzu. Signalspezifische Variablen wie OTEL_EXPORTER_OTLP_TRACES_ENDPOINT werden so verwendet, wie sie sind, müssen also den vollständigen Pfad enthalten.
  • localhost innerhalb eines Containers. Das localhost der App ist die App selbst. Nutze den Service- oder Container-Namen des Collectors.
  • Das SDK ist deaktiviert oder der Exporter ist none. Suche nach OTEL_SDK_DISABLED=true oder OTEL_TRACES_EXPORTER=none.
  • Kein service.name. Daten werden akzeptiert, erscheinen aber als unknown_service, was wie fehlende Daten aussieht. Setze OTEL_SERVICE_NAME.
  • Kurzlebige Prozesse beenden sich vor dem Export. Batch-Exporter senden periodisch, rufe also vor dem Beenden das Shutdown oder Flush des SDKs auf.

Schritt 2: ist der Receiver erreichbar?

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

Eine HTTP-200-Antwort (ein leerer JSON-Body ist in Ordnung) zeigt, dass der HTTP-Receiver erreichbar ist. Für gRPC beweist ein Werkzeug wie grpcurl oder ein TCP-Check (nc -zv collector 4317), dass der Port offen ist. Wenn nicht:

  • Der Receiver ist womöglich an localhost gebunden. Setze endpoint: 0.0.0.0:4317 explizit.
  • Der Kubernetes-Service stellt den Port womöglich nicht bereit, oder der containerPort des Pods fehlt.
  • Eine NetworkPolicy, Firewall oder ein Service Mesh blockiert womöglich den Traffic.

Schritt 3: ist die Pipeline verdrahtet?

Das ist der häufigste Collector-Fehler: eine definierte, aber nicht genutzte Komponente. exporters.otlp/tempo zu definieren bewirkt nichts, bis es in service.pipelines.<signal>.exporters auftaucht. Dasselbe gilt für Receiver, Prozessoren, Extensions und Connectors.

Prüfe:

  • Der Name der Komponente in der Pipeline entspricht exakt ihrer Definition, einschließlich eines Suffixes (otlp/tempo, nicht otlp).
  • Der Signaltyp passt: Eine traces-Pipeline kann keinen Receiver oder Exporter nutzen, der keine Traces unterstützt.
  • Die Extension ist unter service.extensions aufgeführt.
  • Denke bei Helm-Values daran, dass Listen ersetzen, eine teilweise neu definierte Pipeline kann also die Standardkomponenten verloren haben.

Schritt 4: die Daten im Collector sehen

Füge den debug-Exporter zur Pipeline hinzu:

exporters:
  debug:
    verbosity: detailed

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

Lies die Logs des Collectors. Siehst du dort Spans, ist bewiesen, dass Receiver und Prozessoren funktionieren, das Problem liegt also weiter unten. Siehst du nichts, erreichten die Daten die Pipeline nie oder ein Prozessor hat sie verworfen (ein filter-Prozessor oder der Tail Sampler ist der übliche Verdächtige). Entferne debug oder senke seine Ausführlichkeit, wenn du fertig bist, da er jeden Eintrag loggt.

Schritt 5: die eigenen Signale des Collectors nutzen

Health Check:

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

curl http://collector:13133/ gibt einen Status zurück. Nutze es für Kubernetes-Liveness- und Readiness-Probes.

Interne Metriken werden standardmäßig auf Port 8888 bereitgestellt (prüfe service.telemetry.metrics für deine Version):

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

Lies sie als Trichter:

MetrikfamilieBedeutung
otelcol_receiver_accepted_*Erfolgreich empfangene Einträge
otelcol_receiver_refused_*Abgelehnt, oft durch memory_limiter
otelcol_processor_dropped_*Von einem Prozessor verworfen
otelcol_exporter_sent_*An das Backend geliefert
otelcol_exporter_send_failed_*Vom Backend abgelehnt oder nicht erreichbar
otelcol_exporter_queue_size und _capacityQueue-Tiefe gegen ihr Limit

Steigende Accepted-Zahlen bei gleichbleibenden Sent-Zahlen sagen dir, dass das Problem am Exporter liegt. Steigende Refused-Zahlen deuten auf Speicherlimits. Metriknamen wurden zwischen Releases angepasst, prüfe also die Dokumentation zur internen Telemetrie des Collectors für deins.

zPages geben eine Live-Sicht auf Pipelines und aktuelle Traces:

extensions:
  zpages:
    endpoint: localhost:55679

Rufe /debug/tracez und /debug/pipelinez auf (über kubectl port-forward in einem Cluster). Halte es an localhost gebunden.

Schritt 6: nimmt das Backend es an?

Sieh dir Exporter-Fehler in den Collector-Logs an:

  • connection refused oder deadline exceeded: falscher Endpunkt, Port oder eine Netzwerksperre.
  • certificate signed by unknown authority: füge tls.ca_file hinzu oder korrigiere den Endpunkt auf den richtigen Hostnamen.
  • 401 oder 403: Das Token oder der Header fehlt oder ist falsch. Bestätige, dass die Umgebungsvariable im Pod gesetzt ist (kubectl exec ... -- env), da ein nicht gesetztes ${env:VAR} zu einem leeren Wert wird.
  • 415 oder Parsing-Fehler: Protokollabweichung, etwa otlp (gRPC) auf einen HTTP-Port gerichtet.
  • 404 bei HTTP: Prüfe den Basispfad, den das Backend erwartet (Loki nutzt /otlp, Prometheus /api/v1/otlp).
  • Prometheus lehnt OTLP ab: Sein Feature-Flag für den OTLP-Receiver ist nicht aktiviert.

Prüfungen bei Auto-Instrumentierung

Bei Operator-basierter Injection bestätige, dass die Instrumentation vor dem Start des Pods existierte, dass die Annotation auf dem Pod-Template steht und dass der Anwendungs-Pod den Init-Container opentelemetry-auto-instrumentation hat. Starte den Workload nach dem Erstellen oder Ändern der Ressource neu. Bei Agent-basierten Setups bestätige, dass das Agent-Flag oder die Umgebungsvariable tatsächlich angewendet wird (-javaagent:, opentelemetry-instrument, --require).

Kurzreferenz

SymptomZuerst prüfen
Nichts in den Collector-LogsSDK-Endpunkt, Protokoll, Port; localhost in Containern
Collector empfängt Daten, Backend nichtExporter in der Pipeline; Endpunkt; Authentifizierung; Protokoll
Collector startet nichtAusgabe von validate; Komponente fehlt im Image
Daten erscheinen als unknown_serviceOTEL_SERVICE_NAME setzen
Speicherwachstum oder Neustartsmemory_limiter zuerst, Queue-Größen, Ressourcenlimits
Unvollständige Traces nach SamplingEin Trace muss einen Collector erreichen (Load-Balancing-Stufe)
Manche Daten fehlen sporadischQueue voll oder Retry-Limit erreicht; prüfe send_failed und Queue-Metriken

Behebe einen Hop nach dem anderen, halte den debug-Exporter bei der Arbeit griffbereit und lege die internen Metriken des Collectors auf ein Dashboard, damit der nächste Vorfall mit Belegen beginnt.

Beliebte Anleitungen