DevOps
DevOpsFortgeschritten

OpenTelemetry erklärt: Traces, Metriken, Logs und der Collector

Was OpenTelemetry ist und was nicht, wie Traces, Metriken und Logs zusammenhängen, wie API, SDK, OTLP und Collector Daten bewegen, Agent oder Gateway, Zero-Code-Instrumentierung auf Kubernetes, Sampling und die Fehler, die Observability in der Produktion teuer machen.

Titelbild: OpenTelemetry erklärt: Traces, Metriken, Logs und der Collector
Inhalt

Ihr Pager geht um drei Uhr nachts: Die Checkout-Latenz hat sich verdoppelt. Das Dashboard zeigt die Spitze, die Logs aus zwölf Services zeigen nichts Auffälliges, und niemand kann sagen, welcher der vierzig Aufrufe hinter einem Checkout langsam ist. Diese Lücke – zwischen irgendetwas stimmt nicht und genau das stimmt nicht – schließt Observability, und OpenTelemetry ist das Werkzeug, mit dem die meisten Teams sie heute schließen.

Gleichzeitig gehört es zu den am häufigsten missverstandenen Projekten der Cloud-native-Welt. Viele installieren es in der Erwartung eines Monitoring-Produkts und finden eine Spezifikation, ein Dutzend SDKs und einen Collector mit Hunderten Komponenten. Dieser Leitfaden zeigt, wie die Teile zusammenpassen, wie Daten tatsächlich vom Code ins Backend gelangen, wie Sie das Ganze auf Kubernetes betreiben, ohne in Konfiguration zu ertrinken, und welche Entscheidungen es in der Produktion günstig oder teuer machen. Alle Konfigurationen und Codebeispiele wurden gegen OpenTelemetry Collector Contrib v0.162.0 ausgeführt.

OpenTelemetry erklärt: Ein Standard macht aus Aufrufen zwischen Services Traces, Metriken und Logs, die jedes Backend lesen kann.

Was ist OpenTelemetry?

OpenTelemetry (oft kurz OTel) ist ein Open-Source-Framework für Observability, mit dem Sie Telemetrie erzeugen, sammeln und exportieren – Traces, Metriken und Logs. Es ist herstellerneutral: Dieselbe Instrumentierung kann Daten an Jaeger, Prometheus, Grafana, Google Cloud, Datadog oder jedes andere Backend senden, das sein Protokoll versteht.

Genauso wichtig ist, was es nicht ist. Nach eigener Aussage des Projekts ist OpenTelemetry kein Observability-Backend: Speicherung und Visualisierung überlässt es bewusst anderen Werkzeugen. Wer Dashboards sucht, sucht in der falschen Schicht.

Das Projekt beruht auf zwei Versprechen: Die Daten, die Sie erzeugen, gehören Ihnen – ohne Vendor-Lock-in – und Sie lernen einen Satz APIs und Konventionen statt einen pro Anbieter. Es entstand 2019 aus der Fusion von OpenTracing und OpenCensus, zwei älteren Projekten, die dasselbe Problem getrennt lösen wollten. Im Mai 2019 kam es in die CNCF, im August 2021 auf die Stufe Incubating und am 11. Mai 2026 auf Graduated – dieselbe Reifestufe wie Kubernetes und Prometheus.

OpenTelemetry besteht aus:

  • Einer Spezifikation für alle Komponenten und einem Protokoll, OTLP, für den Datentransport.
  • Semantic Conventions – Standardnamen wie http.request.method oder k8s.pod.name, damit jede Bibliothek dasselbe gleich benennt.
  • APIs und SDKs für C++, .NET, Erlang, Go, Java, JavaScript, PHP, Python, Ruby, Rust, Swift und Kotlin.
  • Instrumentierungsbibliotheken und Zero-Code-Instrumentierung, die Telemetrie aus gängigen Frameworks erzeugen, ohne dass Sie Code ändern.
  • Dem Collector, einem Proxy, der Telemetrie empfängt, verarbeitet und exportiert.
  • Dem Kubernetes Operator und Helm Charts, um all das im Cluster zu betreiben.

Monitoring vs. Observability

Beide Begriffe werden oft synonym verwendet, beantworten aber unterschiedliche Fragen.

Monitoring sagt Ihnen, ob etwas nicht stimmt. Sie legen vorher fest, was Sie beobachten – CPU, Fehlerrate, Queue-Länge – und alarmieren, wenn ein Wert eine Schwelle überschreitet. Das funktioniert gut für Ausfälle, die man vorhersehen kann.

Observability lässt Sie herausfinden, warum etwas nicht stimmt, auch bei Ausfällen, die niemand vorhergesehen hat. Die Definition von OpenTelemetry ist kurz: Observability ist die Fähigkeit, den inneren Zustand eines Systems anhand seiner Ausgaben zu verstehen. In Software sind diese Ausgaben Telemetrie, und das System muss instrumentiert sein, um sie zu erzeugen.

Monitoring vs. Observability
Monitoring Observability
Frage Ist das System gesund? Warum verhält es sich so?
Vorab bekannt Die Fehlerbilder Nur die zu sammelnden Ausgaben
Typische Daten Dashboards und Schwellwert-Alerts auf Metriken Traces, Metriken und Logs, filterbar nach jedem Attribut
Stark bei Vorhersehbaren Ausfällen: Platte voll, Pod im Crash-Loop Neuen Ausfällen: ein Mandant langsam auf einem Endpunkt nach einem Deploy

Sie brauchen beides. Monitoring weckt Sie auf, Observability zeigt Ihnen, wo Sie suchen müssen. OpenTelemetry kümmert sich um den zweiten Teil – reichhaltige, zusammenhängende Daten in einer Standardform aus dem System zu holen.

Traces, Metriken und Logs: die drei Signale

OpenTelemetry nennt jede Art von Telemetrie ein Signal. Drei sind heute stabil; ein viertes, Profile, ist noch in Entwicklung.

Die drei OpenTelemetry-Signale: ein Trace aus Spans, Metriken als Zähler und Histogramme und Logs mit derselben Trace-ID.
Eine Anfrage, drei Sichten – und die Trace-ID verbindet sie.

Traces und Spans

Ein Trace ist der Weg einer Anfrage durch Ihr System. Er besteht aus Spans: ein Span pro Arbeitseinheit – ein HTTP-Handler, eine Datenbankabfrage, ein Aufruf beim Zahlungsdienstleister. Jeder Span hat einen Namen, Start- und Endzeit, eine Span-Art (Server, Client, Producer, Consumer oder intern), Attribute, optionale Events und einen Status.

Spans bilden einen Baum. Der erste Span ist der Root Span; jeder andere verweist über eine Parent-Span-ID auf seinen Parent, und alle teilen sich eine Trace-ID. So zeichnet ein Tracing-Backend den Wasserfall mit den 40 Aufrufen hinter einem Checkout – und zeigt, welcher davon 1,8 Sekunden gedauert hat.

Context Propagation

Ein Trace funktioniert über Service-Grenzen nur, wenn die Trace-ID mit der Anfrage mitreist. Das nennt man Context Propagation. OpenTelemetry nutzt standardmäßig den W3C-Trace-Context-Standard: Jede ausgehende HTTP-Anfrage trägt einen traceparent-Header.

traceparent header
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01

Die vier Felder sind die Version (00), die Trace-ID mit 32 Hex-Zeichen, die Parent-Span-ID mit 16 Hex-Zeichen und die Trace Flags (01 bedeutet gesampelt). Ein zweiter Header, baggage, transportiert Schlüssel-Wert-Paare, die jeder nachgelagerte Service sehen soll, etwa eine Mandanten-ID. Für unterstützte HTTP- und gRPC-Bibliotheken setzen und lesen die SDKs beide Header automatisch.

Metriken

Metriken sind über die Zeit aggregierte Zahlen: Anzahl der Anfragen, Latenzverteilungen, Queue-Längen. OpenTelemetry bietet Counter (steigen nur), Up-Down-Counter, Histogramme (Verteilungen wie die Antwortzeit) und Gauges (aktueller Wert), jeweils synchron zum Aufruf aus dem Code und asynchron, vom SDK abgefragt.

Metriken sind günstig zu speichern, weil sie aggregiert sind – ein Histogramm fasst Millionen Anfragen zusammen. Ihre Schwäche ist die Kardinalität, dazu unten ein eigener Abschnitt. Exemplars verbinden beide Welten: Ein Latenz-Histogramm kann die Trace-ID einer Beispielanfrage mitführen, sodass Sie von einem langsamen Bucket direkt zu einem echten Trace springen.

Logs

OpenTelemetry verlangt nicht, dass Sie Ihr Logging umschreiben. Eine Logs Bridge verbindet stattdessen vorhandene Bibliotheken – logging in Python, Log4j oder Logback in Java und so weiter – mit dem SDK. Jeder Eintrag wird als OTLP-Log mit Trace-ID und Span-ID des aktiven Spans exportiert, sodass Sie in einem Trace genau die Logzeilen sehen, die währenddessen geschrieben wurden.

Der Collector kann außerdem Logs lesen, die nie durch ein SDK gingen, etwa Container-Logdateien auf einem Node, und sie ins selbe Format bringen.

Wie OpenTelemetry funktioniert: API, SDK, OTLP und Collector

Die Architektur hat vier Schichten, und wer sie verwechselt, wird schnell frustriert.

  • Die API ist das, was Ihr Code und Ihre Bibliotheken aufrufen: einen Tracer holen, einen Span starten, eine Metrik erfassen. Allein bewirkt sie nichts – Aufrufe sind No-ops, bis ein SDK installiert ist. Das ist Absicht: Eine Bibliothek kann mit der API instrumentiert werden, ohne jeden Nutzer zu Telemetrie zu zwingen.
  • Das SDK implementiert die API. Es sampelt Spans, aggregiert Metriken, ergänzt Resource-Attribute, die den Prozess beschreiben (service.name, service.version, k8s.pod.name), bündelt die Daten und übergibt sie an einen Exporter.
  • OTLP ist das Protokoll, das der Exporter spricht.
  • Der Collector ist ein optionaler, aber fast immer vorhandener Zwischenschritt zwischen Anwendungen und Backends.

OTLP, das Übertragungsprotokoll

OTLP überträgt alle drei stabilen Signale über zwei Transportwege:

OTLP, das Übertragungsprotokoll
OTLP/gRPC OTLP/HTTP
Standardport 4317 4318
Kodierung Protobuf Binäres Protobuf oder JSON
Pfade gRPC-Services /v1/traces, /v1/metrics, /v1/logs
Gut für Service zu Collector, Collector zu Collector Browser, Proxys, Firewalls, die nur HTTP erlauben

Das Protokoll legt fest, wie man sich bei Fehlern verhält – wichtig, wenn Telemetrie während eines Vorfalls sprunghaft ansteigt. Über HTTP sind 429, 502, 503 und 504 wiederholbar, und ein Retry-After-Header muss beachtet werden; ein 400 heißt, die Daten sind fehlerhaft und werden verworfen, nicht wiederholt. Ein Server kann auch nur einen Teil eines Batches annehmen und melden, wie viele Einträge er abgelehnt hat. Die Spezifikation empfiehlt eine Grenze von 64 MiB pro Anfrage und nimmt in Kauf, dass ein Retry nach einem Netzwerkfehler Duplikate erzeugen kann – ein bewusster Kompromiss für Telemetrie.

OTLP lässt sich mit nichts außer curl ausprobieren. Mit einem lokalen Collector auf Port 4318 erzeugt diese Anfrage einen Span:

send-span.sh
curl -X POST http://127.0.0.1:4318/v1/traces \
-H 'Content-Type: application/json' \
-d '{"resourceSpans":[{"resource":{"attributes":[
{"key":"service.name","value":{"stringValue":"checkout"}}]},
"scopeSpans":[{"scope":{"name":"manual-test"},"spans":[{
"traceId":"5b8efff798038103d269b633813fc60c",
"spanId":"eee19b7ec3c1b174",
"name":"POST /checkout","kind":2,
"startTimeUnixNano":"1760425200000000000",
"endTimeUnixNano":"1760425200250000000"}]}]}]}'
# → {"partialSuccess":{}} HTTP 200

Beachten Sie die Details der JSON-Kodierung: Trace- und Span-IDs sind Hex-Strings, nicht Base64, und kind ist die Zahl 2 (Server), kein Name.

Der OpenTelemetry Collector

Der Collector ist ein einzelnes Go-Binary, konfiguriert mit YAML. Er ist der Teil von OpenTelemetry, den Betriebsteams tatsächlich betreiben, und es lohnt sich, ihn richtig zu verstehen.

Im OpenTelemetry Collector: Receiver speisen Prozessoren in fester Reihenfolge, Exporter senden an Backends, Connectoren verbinden Pipelines.
Die Reihenfolge zählt: zuerst begrenzen und verwerfen, in der Mitte anreichern, zuletzt bündeln.

Receiver, Prozessoren, Exporter und Connectoren

Eine Konfiguration kennt vier Arten von Pipeline-Komponenten:

  • Receiver holen Daten herein. otlp ist der wichtigste; andere scrapen Prometheus-Endpunkte, lesen Kafka-Topics, folgen Logdateien oder sammeln Host-Metriken.
  • Prozessoren verändern Daten unterwegs: Speicher begrenzen, filtern, Attribute ergänzen oder löschen, sampeln, bündeln.
  • Exporter senden Daten hinaus – an einen anderen Collector, Prometheus, Google Cloud, Datadog, eine Datei oder an den debug-Exporter, der auf die Konsole schreibt.
  • Connectoren verbinden zwei Pipelines und sind auf der einen Seite Exporter, auf der anderen Receiver. Der spanmetrics-Connector etwa macht aus Spans Metriken für Anfragerate, Fehler und Dauer.

Eine Komponente zu definieren, bewirkt allein nichts. Sie läuft erst, wenn Sie sie unter service.pipelines in einer Pipeline aufführen, getrennt für traces, metrics und logs.

Die Reihenfolge der Prozessoren ist keine Kosmetik

Prozessoren laufen in der Reihenfolge, in der Sie sie auflisten, und das Projekt dokumentiert eine empfohlene Reihenfolge:

  1. memory_limiter zuerst, damit der Collector Daten ablehnen kann, bevor ihm der Speicher ausgeht.
  2. Sampling und Filter als Nächstes, damit keine CPU für Daten verloren geht, die gleich verworfen werden.
  3. Prozessoren, die den Request-Kontext brauchen, etwa k8sattributes, vor dem Batching – das Batching löscht diesen Kontext.
  4. Anreicherung und Transformation: attributes, transform, resource.
  5. Batching zuletzt, am besten im Exporter selbst über seine Sending Queue statt über einen eigenen batch-Prozessor.

Hier eine vollständige Agent-Konfiguration, wie sie auf jedem Kubernetes-Node laufen würde:

otel-agent.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 20
k8sattributes:
extract:
metadata: [k8s.namespace.name, k8s.deployment.name, k8s.pod.name, k8s.node.name]
resourcedetection:
detectors: [env, gcp]
timeout: 5s
attributes/scrub:
actions:
- key: http.request.header.authorization
action: delete
- key: user.email
action: hash
exporters:
otlp_grpc/gateway:
endpoint: otel-gateway.observability.svc.cluster.local:4317
sending_queue:
batch:
extensions:
health_check:
endpoint: 0.0.0.0:13133
service:
extensions: [health_check]
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, k8sattributes, resourcedetection, attributes/scrub]
exporters: [otlp_grpc/gateway]
metrics:
receivers: [otlp]
processors: [memory_limiter, k8sattributes, resourcedetection]
exporters: [otlp_grpc/gateway]
logs:
receivers: [otlp]
processors: [memory_limiter, k8sattributes, resourcedetection, attributes/scrub]
exporters: [otlp_grpc/gateway]

In dieser Datei stecken zwei Sicherheitsdetails. Der Collector bindet standardmäßig an localhost; 0.0.0.0 ist in einem Pod nötig, damit andere Pods ihn erreichen, und sollte dann per NetworkPolicy abgesichert werden. Und der Prozessor attributes/scrub ist die günstigste Stelle in Ihrem gesamten Stack, um zu verhindern, dass ein Authorization-Header oder eine E-Mail-Adresse in einem fremden Backend landet.

Welche Collector-Distribution?

Der Collector wird aus Komponenten gebaut, und mehrere Distributionen bündeln unterschiedliche Sätze:

  • otelcol (Core) – eine kleine Auswahl an Upstream-Komponenten.
  • otelcol-contrib – fast alle Community-Komponenten; bequem zum Lernen, für die Produktion größer als nötig.
  • otelcol-k8s – für Kubernetes ausgewählte Komponenten.
  • Hersteller-Distributionen wie der Google-Built OpenTelemetry Collector oder Grafana Alloy, getestet gegen eine Plattform.
  • Ihr eigener Build mit dem OpenTelemetry Collector Builder (ocb), der genau die Komponenten enthält, die Sie nutzen – die kleinste Angriffsfläche.

Agent oder Gateway: wie Sie den Collector betreiben

Es gibt zwei Bausteine, und die meisten Produktionsumgebungen nutzen beide.

Betriebsmodelle für den OpenTelemetry Collector: direkter Export, ein Agent auf jedem Node und Agent plus Gateway mit Tail Sampling.
Mit Agents beginnen; ein Gateway ergänzen, wenn Sie eine zentrale Stelle für Regeln brauchen.

Ein Agent läuft nah an der Anwendung – als DaemonSet auf jedem Kubernetes-Node oder als Sidecar. Anwendungen senden an einen lokalen Endpunkt, was ihre Konfiguration trivial hält, und der Agent ergänzt Host- und Pod-Metadaten günstig, weil er auf demselben Node läuft.

Ein Gateway ist ein zentraler, horizontal skalierter Pool von Collectoren hinter einem OTLP-Endpunkt – meist einer pro Cluster oder Region. Die offizielle Deployment-Anleitung nennt als Vorteile zentral verwaltete Credentials und zentrale Regeln wie Filter und Sampling, als Kosten eine weitere Komponente, die gewartet werden muss und ausfallen kann, zusätzliche Latenz und mehr Ressourcenverbrauch.

Agent oder Gateway: wie Sie den Collector betreiben
Direkter Export Nur Agent Agent + Gateway
Bewegliche Teile Keine Ein DaemonSet DaemonSet + Deployment
Backend-Credentials In jeder Anwendung Auf jedem Node An einer Stelle
Kubernetes-Metadaten Vom SDK Ja, günstig Ja, vom Agent ergänzt
Tail Sampling Nein Nein Ja
Fan-out an mehrere Backends Pro Anwendung Pro Node Zentral
Geeignet für Prototypen, wenige Services Die meisten Cluster Plattformen mit vielen Teams, regulierte Daten, hohes Volumen

Tail Sampling braucht alle Spans an einer Stelle

Tail Sampling ist der Hauptgrund für ein Gateway, und es hat einen Haken: Ein Sampler kann einen Trace nur beurteilen, wenn er alle seine Spans sieht, während diese Spans von vielen Pods kommen. Die dokumentierte Lösung sind zwei Schichten. Die erste nutzt den load_balancing-Exporter mit routing_key: traceID, um alle Spans eines Traces an dieselbe Instanz der zweiten Schicht zu senden, die den Prozessor tail_sampling ausführt.

Die folgende Konfiguration der zweiten Schicht behält jeden Fehler, jeden Trace über zwei Sekunden und 10 % vom Rest – und berechnet Metriken für Anfragerate, Fehler und Dauer aus allen Spans vor dem Sampling, sodass Dashboards korrekt bleiben, obwohl nur ein Teil der Traces gespeichert wird:

otel-gateway.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
connectors:
spanmetrics: # RED metrics from 100% of spans, before sampling
forward/sample: # hands the same spans to the sampling pipeline
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 20
tail_sampling:
decision_wait: 10s
num_traces: 100000
policies:
- name: keep-errors
type: status_code
status_code: { status_codes: [ERROR] }
- name: keep-slow
type: latency
latency: { threshold_ms: 2000 }
- name: sample-the-rest
type: probabilistic
probabilistic: { sampling_percentage: 10 }
resource/gcp:
attributes:
- key: gcp.project_id
value: ${env:GOOGLE_CLOUD_PROJECT}
action: insert
exporters:
otlp_http/gcp:
endpoint: https://telemetry.googleapis.com
encoding: proto
auth: { authenticator: googleclientauth }
sending_queue:
batch:
extensions:
googleclientauth:
service:
extensions: [googleclientauth]
pipelines:
traces/in:
receivers: [otlp]
processors: [memory_limiter]
exporters: [spanmetrics, forward/sample]
traces/sampled:
receivers: [forward/sample]
processors: [tail_sampling, resource/gcp]
exporters: [otlp_http/gcp]
metrics/red:
receivers: [spanmetrics]
processors: [resource/gcp]
exporters: [otlp_http/gcp]

Die Regeln werden gemeinsam ausgewertet: Ein Trace bleibt erhalten, wenn irgendeine von ihnen zustimmt. decision_wait legt fest, wie lange das Gateway einen Trace puffert, bevor es entscheidet, und num_traces begrenzt, wie viele es im Speicher hält – dimensionieren Sie beides nach Ihrem Verkehr, denn diese Schicht ist zustandsbehaftet.

Eine Regel für Metriken: ein einziger Writer

Exportieren mehrere Collectoren denselben Metrik-Stream, können sie sich gegenseitig überschreiben und in Prometheus Lücken, Sprünge und Fehler wie „out-of-order sample” erzeugen. Das OpenTelemetry-Datenmodell verlangt für jeden Metrik-Stream einen einzigen Writer. In der Praxis heißt das: Jeder Stream braucht Attribute, die seine Herkunft eindeutig machen – k8sattributes und resourcedetection liefern sie –, und zwei Collectoren dürfen nicht dasselbe Ziel scrapen.

Code instrumentieren

Es gibt zwei Wege, eine Anwendung Telemetrie erzeugen zu lassen, und Sie werden beide nutzen.

Zero-Code-Instrumentierung

Zero-Code-Instrumentierung (auch automatische Instrumentierung) hängt sich zur Laufzeit in gängige Frameworks und Clients – Webserver, HTTP-Clients, Datenbanktreiber, Message Queues – und erzeugt dafür Spans und Metriken, ohne dass Sie den Quellcode anfassen.

Python
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install # adds instrumentation for installed libraries
OTEL_SERVICE_NAME=checkout \
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317 \
opentelemetry-instrument python app.py
Node.js
npm install --save @opentelemetry/api @opentelemetry/auto-instrumentations-node
export OTEL_SERVICE_NAME=checkout
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317
export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
node app.js

Für Java ist das Gegenstück der OpenTelemetry-Java-Agent, eingebunden mit -javaagent:opentelemetry-javaagent.jar. Python arbeitet per Monkey Patching der Bibliotheken zur Laufzeit, der Java-Agent per Bytecode-Umschreibung beim Laden der Klassen.

Manuelle Spans dort, wo die Geschäftslogik liegt

Automatische Instrumentierung sieht HTTP und SQL. Sie sieht nicht, dass eine Anfrage eine Erstattung war, zu welchem Mandanten sie gehörte oder dass der Zahlungsdienstleister beim dritten Versuch in ein Timeout lief. Das ergänzen Sie mit wenigen Zeilen API:

payments.py
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
provider = TracerProvider(resource=Resource.create({"service.name": "checkout"}))
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("checkout.payments")
def charge(order_id: str, amount_cents: int) -> None:
with tracer.start_as_current_span("charge card") as span:
span.set_attribute("order.id", order_id)
span.set_attribute("payment.amount_cents", amount_cents)
try:
call_payment_provider(order_id, amount_cents)
except TimeoutError as exc:
span.record_exception(exc)
span.set_status(trace.Status(trace.StatusCode.ERROR, "provider timeout"))
raise

Läuft der Zahlungsdienstleister in ein Timeout, erhält der Collector einen Span namens charge card mit Status Error, der Meldung provider timeout, beiden Attributen und einem Exception-Event mit dem Stacktrace. Nutzen Sie zusätzlich Zero-Code-Instrumentierung, lassen Sie die Provider-Zeilen weg – der Agent konfiguriert das SDK, und Ihr Code braucht nur trace.get_tracer.

Halten Sie sich bei allem, was bereits einen Standardnamen hat (http.request.method, db.system.name, messaging.system), an die Semantic Conventions, und nutzen Sie für den Rest einen eigenen Namensraum wie payment.amount_cents.

Reifegrad nach Sprache

Traces sind in fast allen Sprachen stabil, Metriken in den meistgenutzten, Logs nur in einigen. Die offizielle Statustabelle:

Reifegrad nach Sprache
Sprache Traces Metriken Logs
Java, .NET, C++, PHP Stabil Stabil Stabil
Go Stabil Stabil Release Candidate
Python, JavaScript Stabil Stabil Development
Rust Beta Stabil Stabil
Ruby, Swift, Erlang/Elixir Stabil Development Development
Kotlin Development Development Development

Development heißt nicht unbrauchbar – viele Teams verschicken Python-Logs über OpenTelemetry –, aber APIs können sich zwischen Releases noch ändern. Pinnen Sie die Versionen.

OpenTelemetry auf Kubernetes betreiben

Der OpenTelemetry Operator verwaltet im Cluster zweierlei: Collectoren über eine OpenTelemetryCollector-Ressource, die als Deployment, DaemonSet, StatefulSet oder Sidecar laufen kann, und die automatische Instrumentierung über eine Instrumentation-Ressource. Für seinen Admission Webhook braucht er meist cert-manager.

Die Instrumentation-Ressource beschreibt, wohin Daten gehen und wie gesampelt wird:

instrumentation.yaml
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: default
namespace: shop
spec:
exporter:
endpoint: http://otel-agent.observability.svc.cluster.local:4318
propagators: [tracecontext, baggage]
sampler:
type: parentbased_traceidratio
argument: "0.25"

Anwendungen melden sich mit einer Annotation am Pod-Template an:

deployment.yaml (excerpt)
spec:
template:
metadata:
annotations:
instrumentation.opentelemetry.io/inject-python: "true"

Läuft der Agent als DaemonSet, geben Sie seinem Service internalTrafficPolicy: Local, damit jeder Pod an den Agent auf seinem eigenen Node sendet statt an einen beliebigen im Cluster.

Beim Start des Pods ergänzt der Operator einen Init-Container, der die Instrumentierung in den Pod kopiert und die Umgebungsvariablen setzt. Drei Details verursachen die meisten gescheiterten Rollouts:

  • Die Reihenfolge zählt. Die Instrumentation-Ressource muss existieren, bevor die Pods starten; vorher erzeugte Pods werden erst nach einem Neustart instrumentiert.
  • Die Annotation gehört nach spec.template.metadata.annotations, nicht in die Metadaten des Deployments selbst.
  • Die Protokolle unterscheiden sich je Sprache. Die Python-Injektion unterstützt nur OTLP über HTTP, der Endpunkt braucht also Port 4318; Node.js nutzt standardmäßig gRPC auf 4317. Go wird über einen privilegierten eBPF-Sidecar instrumentiert und ist hinter einem Feature Gate standardmäßig deaktiviert.

Auf GKE können Sie auf eigene Collectoren verzichten: Google bietet Managed OpenTelemetry for GKE an und veröffentlicht außerdem den Google-Built OpenTelemetry Collector mit einer geprüften Konfiguration, falls Sie lieber selbst betreiben. Der Rest des Cluster-Designs – Workload Identity, NetworkPolicies, Platz des Gateways – fügt sich in dieselbe Struktur wie die Secure-by-default-Referenzarchitektur für GKE.

Wohin die Daten gehen: ein Backend wählen

OpenTelemetry endet beim Exporter. Alles danach ist eine Backend-Entscheidung, und weil jedes ernsthafte Backend inzwischen OTLP annimmt, können Sie es sich später anders überlegen.

Wohin die Daten gehen: ein Backend wählen
Backend Signale Wie es OpenTelemetry empfängt Gut zu wissen
Prometheus Metriken Nativer OTLP-Receiver unter /api/v1/otlp/v1/metrics, aktiviert mit --web.enable-otlp-receiver; oder per Scraping über den Collector Nur HTTP; Out-of-order-Ingestion aktivieren (30 Minuten sind ein guter Start), wenn mehrere Collectoren schreiben
Grafana Tempo / Loki / Mimir Traces / Logs / Metriken OTLP Loki speichert die meisten Attribute als Structured Metadata und erlaubt standardmäßig 15 Index-Labels – k8s.pod.name gehört nicht in die Labels
Jaeger v2 Traces OTLP; Jaeger v2 baut selbst auf dem Collector-Framework auf All-in-one mit In-Memory-Speicher nur für Entwicklung
Google Cloud Observability Alle drei Telemetry (OTLP) API unter telemetry.googleapis.com, gRPC oder HTTP Verlangt gcp.project_id an der Resource; Metriken landen als Prometheus-Zeitreihen
Datadog, New Relic, Dynatrace, Honeycomb Alle drei OTLP-Endpunkte oder Collector-Exporter Ihre Analyse bleibt, der proprietäre Agent fällt weg

Speziell auf Google Cloud nimmt die Telemetry API alle drei Signale über einen Endpunkt an. Der Schreibende braucht die Rolle roles/telemetry.writer plus Service Usage Consumer im Quota-Projekt, und die Authentifizierung im Collector läuft über die Extension googleclientauth – idealerweise mit Workload Identity statt einer Schlüsseldatei, aus den Gründen, die in Service-Account-Schlüssel abschaffen mit Workload Identity Federation stehen. Das Standardkontingent für Metriken liegt bei 60.000 Anfragen pro Minute und Region mit bis zu 200 Punkten pro Anfrage – rund 200.000 Samples pro Sekunde –, und die Metrik-Ingestion darüber braucht Collector 0.140.0 oder neuer.

OpenTelemetry vs. Prometheus vs. Hersteller-Agents

Nach diesem Vergleich wird oft gesucht, und die ehrliche Antwort lautet: Die drei konkurrieren nicht auf derselben Ebene.

OpenTelemetry vs. Prometheus vs. Hersteller-Agents
OpenTelemetry Prometheus Hersteller-Agent (Datadog, Dynatrace …)
Was es ist Standard + SDKs + Collector Metrik-Datenbank, Abfragesprache und Alerting Proprietäre Erfassung für ein Backend
Signale Traces, Metriken, Logs (Profile folgen) Metriken Meist alle, plus Extras des Herstellers
Modell Meist Push über OTLP Meist Pull (Scraping) Push zum Hersteller
Speicherung und UI Keine – Ihre Wahl Ja Die des Herstellers
Lock-in Keiner Gering Hoch
Ersetzt Hersteller-SDKs und -Agents Nichts in OpenTelemetry; es ist ein Backend —

Die praktische Antwort auf „OpenTelemetry oder Prometheus?“ lautet daher meist beides: mit OpenTelemetry instrumentieren und Metriken in Prometheus oder einem Managed-Prometheus-Dienst speichern. Und die Antwort auf „OpenTelemetry oder Datadog?” lautet: OpenTelemetry ersetzt den Datadog-Agent, nicht Datadog – Sie behalten das Produkt und gewinnen die Freiheit, es zu verlassen.

Sampling: die Traces behalten, die zählen

Im großen Maßstab können Sie sich nicht leisten, jeden Trace zu speichern, und Sie müssen es auch nicht. Die OpenTelemetry-Dokumentation empfiehlt, Sampling ab etwa 1.000 Traces pro Sekunde in Betracht zu ziehen, und weist darauf hin, dass bei hohem Volumen eine Stichprobe von 1 % oder weniger den Rest zuverlässig abbilden kann.

  • Head Sampling entscheidet, wenn der Root Span beginnt. Die übliche Wahl ist parentbased_traceidratio: Der Root-Service behält einen festen Anteil der Traces, ausgewählt nach Trace-ID, und jeder nachgelagerte Service folgt der Entscheidung des Parents – so entstehen nie halbe Traces. Das ist günstig und zustandslos, weiß aber nicht, ob der Trace mit einem Fehler endet.
  • Tail Sampling entscheidet nach Abschluss des Traces und kann daher jeden Fehler und jede langsame Anfrage behalten. Es braucht die oben beschriebene zustandsbehaftete Gateway-Schicht und ist schwerer zu dimensionieren und zu betreiben.

Viele Teams kombinieren beides: ein großzügiges Head Sampling, um die Pipeline vor Überlast zu schützen, und danach Tail Sampling im Gateway, um auszuwählen, welche Traces das Geld wert sind. Eine Regel macht beide Wege sicher – berechnen Sie Metriken, bevor Sie Traces sampeln, wie es der spanmetrics-Connector in der Gateway-Konfiguration tut, damit Dashboards und SLOs auf 100 % der Anfragen beruhen.

Fehler in der Produktion, die OpenTelemetry teuer machen

Fast jedes Kostenproblem mit OpenTelemetry geht auf eine Handvoll Fehler zurück.

Metrik-Kardinalität. Jede eindeutige Kombination von Attributwerten ist eine eigene Zeitreihe. Ein Latenz-Histogramm mit http.route und http.response.status_code ist in Ordnung; fügen Sie user.id oder order.id hinzu, entsteht eine Zeitreihe pro Kunde. Halten Sie Kennungen auf Spans und Logs – dort sind sie nützlich – und aus Metriken heraus. Entfernen Sie problematische Attribute im Collector mit dem Prozessor attributes oder transform.

Jeden gesunden Trace behalten. Ein erfolgreicher GET /health, der zu 100 % getraced wird, ist reine Kosten. Filtern Sie Health Checks ganz heraus und sampeln Sie den Rest.

Personenbezogene Daten in Attributen. Instrumentierung kann URLs mit Query-Strings, Header und SQL-Statements erfassen. Bereinigen oder hashen Sie alles Personenbezogene im Agent, bevor es den Node verlässt – die günstigste DSGVO-Maßnahme, die Sie je einführen werden.

Logs, die in jeden Eintrag kopiert werden. Manche Backends kopieren Resource- und Scope-Attribute in jeden gespeicherten Logeintrag, sodass eine große Resource das Logvolumen vervielfacht. Die Dokumentation von Google Cloud weist ausdrücklich darauf hin; kürzen Sie Resource-Attribute vor dem Export.

Ein Collector ohne Grenzen. Ohne memory_limiter kann ein Vorfall, der den Verkehr verdoppelt, den Collector genau dann zum Absturz bringen, wenn Sie ihn brauchen. Beobachten Sie seine eigenen Metriken – abgelehnte, verworfene und wartende Einträge – und dimensionieren Sie das Gateway für Verkehr wie im Vorfall, nicht für einen durchschnittlichen Tag.

Abgerissener Kontext an asynchronen Grenzen. Traces, die an einer Queue enden, bedeuten meist einen Producer, der keinen Kontext mitgibt. Für Batch-Consumer, die viele Nachrichten auf einmal verarbeiten, verbinden Sie einen Consumer-Span über Span Links mit vielen Producer-Spans, statt einen einzigen Parent zu erzwingen.

Telemetrie ist eine Datenpipeline wie jede andere. Geben Sie ihr ein Budget, begrenzen Sie die Rate, bereinigen Sie sie und überwachen Sie sie – sonst wird sie unbemerkt zum teuersten und am wenigsten vertrauenswürdigen System, das Sie betreiben.

Checkliste für die Produktion

Instrumentierung:

  • service.name, service.version und deployment.environment.name an jedem Service gesetzt
  • Zero-Code-Instrumentierung aktiv, manuelle Spans um Geschäftsvorgänge
  • Semantic Conventions für Standardattribute; eigener Namensraum für den Rest
  • Kontext über HTTP, gRPC und Message Queues weitergegeben
  • Versionen von SDK und Instrumentierung gepinnt

Collector:

  • Agent als DaemonSet; Gateway nur dort, wo zentrale Regeln oder Tail Sampling nötig sind
  • memory_limiter zuerst, Batching zuletzt, k8sattributes vor dem Batching
  • PII im Agent bereinigt; Credentials nur im Gateway oder über Workload Identity
  • Konfigurationen in der CI mit otelcol validate geprüft; eigener schlanker Build in der Produktion
  • Eigene Metriken und Health Check des Collectors überwacht und alarmiert

Daten und Kosten:

  • Keine Nutzer- oder Anfrage-IDs in Metrik-Attributen
  • Health Checks gefiltert; Head und/oder Tail Sampling eingerichtet
  • Span-Metriken vor dem Sampling berechnet
  • Ein Writer pro Metrik-Stream
  • Backend pro Signal gewählt; überall OTLP, damit es später wechseln kann

Fazit

OpenTelemetry ist kein Produkt, das Sie kaufen, und kein Dashboard, das Sie installieren. Es ist die Verrohrung: eine gemeinsame Art, wie jeder Service beschreibt, was er tut, ein gemeinsames Protokoll, um diese Beschreibung zu transportieren, und ein Collector, der entscheidet, was bleibt, was bereinigt wird und wohin es geht.

Der Gewinn ist Hebelwirkung. Einmal instrumentiert, können Sie das Backend wechseln, während einer Migration an zwei gleichzeitig senden oder Tail Sampling für das ganze Unternehmen einführen, indem Sie eine Gateway-Konfiguration ändern – ohne den Anwendungscode anzufassen. Machen Sie die langweiligen Teile richtig – Namen, Kardinalität, Sampling und einen Collector, der nicht umfallen kann –, und die Frage um drei Uhr nachts ändert sich von „Wo fangen wir überhaupt an?“ zu „Klick auf den langsamen Span.”

Observability ist die Datenseite der Arbeit eines Plattformteams – Platform Engineering auf Kubernetes beschreibt den Rest des Paved Road.

Häufig gestellte Fragen

Was ist OpenTelemetry einfach erklärt?

OpenTelemetry ist ein Open-Source-Standard, um Telemetrie aus Software zu gewinnen – Traces, die einer Anfrage durch mehrere Services folgen, Metriken, die zählen und messen, und Logs, die Ereignisse festhalten. Sie bekommen einheitliche APIs und SDKs für alle wichtigen Sprachen, ein Protokoll namens OTLP und einen Collector, der Daten empfängt, verarbeitet und weiterleitet. Gespeichert oder angezeigt wird nichts; die Daten gehen an ein Backend Ihrer Wahl. Das Projekt gehört zur CNCF und hat im Mai 2026 den Status Graduated erreicht.

Was ist der Unterschied zwischen OpenTelemetry und Prometheus?

Prometheus ist eine Metrik-Datenbank mit Alerting, die Metriken meist per Scraping von HTTP-Endpunkten abholt. OpenTelemetry ist ein herstellerneutraler Weg, Traces, Metriken und Logs zu erzeugen und zu transportieren, meist per Push über OTLP. Beide ergänzen sich: Der OpenTelemetry Collector kann Prometheus-Endpunkte scrapen und nach Prometheus exportieren, und Prometheus selbst nimmt OTLP-Metriken an, wenn es mit --web.enable-otlp-receiver gestartet wird. Typisch ist OpenTelemetry für Instrumentierung und Transport und Prometheus oder ein Managed-Prometheus-Dienst für Speicherung und Alerts.

Was ist der OpenTelemetry Collector?

Der Collector ist ein einzelnes Binary, das Telemetrie empfängt, verarbeitet und exportiert. Eine Konfiguration definiert Receiver (OTLP, Prometheus, Kafka und viele mehr), Prozessoren (Speicherbegrenzung, Batching, Filter, Attributänderungen, Sampling) und Exporter (OTLP, Prometheus, Google Cloud, Datadog und andere), verbunden zu Pipelines pro Signal. So bleiben Credentials und Retries aus Ihren Anwendungen heraus, und Sie können das Backend wechseln, ohne Code neu auszurollen.

Was ist OTLP?

OTLP, das OpenTelemetry Protocol, ist Datenformat und Transport für Telemetrie. Es überträgt Traces, Metriken und Logs – Profile sind noch in Entwicklung – als Protocol Buffers über gRPC auf Port 4317 oder über HTTP auf Port 4318, wobei HTTP binäres Protobuf oder JSON unter /v1/traces, /v1/metrics und /v1/logs annimmt. Es legt fest, welche Fehler wiederholt werden dürfen, wie Server Gegendruck signalisieren und wie ein Teilerfolg gemeldet wird.

Brauche ich den OpenTelemetry Collector, oder können Anwendungen direkt senden?

Anwendungen können direkt an jedes Backend exportieren, das OTLP annimmt, und für einen kleinen Service ist das in Ordnung. In der Produktion setzen die meisten Teams einen Collector davor, weil er Batching und Retries außerhalb der Anwendung erledigt, Backend-Credentials an einer Stelle hält, Daten mit Kubernetes-Metadaten anreichert, sensible Attribute entfernt und Tail Sampling ermöglicht. Auch die Dokumentation des OpenTelemetry Operators empfiehlt, aus Containern an einen Collector statt direkt an ein Backend zu senden.

Was ist der Unterschied zwischen Head Sampling und Tail Sampling?

Head Sampling entscheidet am Anfang eines Traces, meist anhand der Trace-ID und eines festen Anteils. Das ist günstig und einfach, kann aber nicht wissen, ob der Trace einen Fehler enthalten wird. Tail Sampling wartet, bis ein Trace vollständig ist, und entscheidet nach seinem Inhalt – alle Fehler behalten, alles über zwei Sekunden behalten, 10 % vom Rest. Dafür braucht es eine zustandsbehaftete Collector-Schicht, in der alle Spans eines Traces bei derselben Instanz ankommen.

Ist OpenTelemetry produktionsreif?

Ja für Traces und Metriken in Java, .NET, Go, Python, JavaScript, C++ und PHP und für Logs in Java, .NET, C++, PHP und Rust; Logs in Python und JavaScript sind noch als Development markiert, Go ist Release Candidate. OTLP ist für Traces, Metriken und Logs stabil. Collector-Komponenten haben jeweils einen eigenen Stabilitätsgrad, prüfen Sie also das README jedes Receivers, Prozessors und Exporters, auf den Sie sich verlassen. In der CNCF ist das Projekt seit Mai 2026 Graduated.

Wie füge ich OpenTelemetry zu einer Python-Anwendung hinzu?

Installieren Sie Distro und Exporter mit pip install opentelemetry-distro opentelemetry-exporter-otlp, führen Sie opentelemetry-bootstrap -a install aus, um Instrumentierung für die bereits genutzten Bibliotheken zu ergänzen, und starten Sie die Anwendung mit opentelemetry-instrument python app.py. Mit OTEL_SERVICE_NAME und OTEL_EXPORTER_OTLP_ENDPOINT benennen Sie den Service und zeigen auf Ihren Collector. Auf Kubernetes kann der OpenTelemetry Operator dieselbe Instrumentierung per Pod-Annotation einspielen.

Ersetzt OpenTelemetry Datadog, New Relic oder Dynatrace?

Nein. OpenTelemetry ersetzt deren proprietäre Agents und SDKs für die Datenerfassung, nicht deren Speicherung, Dashboards und Analyse. Alle großen Anbieter nehmen OTLP an, Sie können also einmal mit OpenTelemetry instrumentieren und das Backend später wechseln – oder während einer Migration dieselben Daten an zwei Backends senden –, ohne den Anwendungscode anzufassen.

Aus der Community

Diskussion auf Mastodon & Bluesky

Antworten auf diesen Artikel aus dem offenen Netz, live geladen. Keine Werbung, keine Tracking-Skripte.

Antworten werden geladen …
Auf Mastodon antwortenAuf Bluesky antworten

Antworte dort — es erscheint hier automatisch.

ENDE