Observability & Monitoring

Observability mit OpenTelemetry: Logs, Metriken und Traces zusammenbringen

Sobald eine Anfrage durch fünf Dienste läuft, sagt dir ein Dashboard mit Auslastungswerten nichts mehr über die Ursache. OpenTelemetry liefert die fehlende dritte Signalart, den Trace, und zwar herstellerneutral über ein einziges Format. Der Aufwand steckt weniger in der Instrumentierung, die für die meisten Sprachen ohne Codeänderung funktioniert, als in der Frage, wie viele Daten du dauerhaft bezahlen willst.

5 Kapitel mit allen Befehlen
Einsteigerin in die Cloud-Administration an zwei Monitoren mit Dashboards
Seit 1997 am Markt Präsenz & Live-Online 4,9 aus 503 Google-Bewertungen Auch Inhouse für dein Team
Worum es geht

Warum klassisches Monitoring bei verteilten Systemen aussteigt

Klassisches Monitoring beantwortet die Frage, ob ein Server läuft. In einer Umgebung mit einem Dutzend Diensten, die sich gegenseitig aufrufen, ist das die falsche Frage. Der Alarm kommt von dem Dienst, der als letzter langsam wird, die Ursache liegt drei Aufrufe weiter hinten in einer Datenbankabfrage oder in einer überlaufenden Warteschlange. Dashboards mit Auslastung und Speicherverbrauch zeigen dann überall gelbe Werte und nirgends die Ursache. Die Fehlersuche wird zur Telefonkonferenz, in der jedes Team nachweist, dass es nicht schuld ist.

Dazu kommt die Werkzeugfrage. Metriken liegen in Prometheus, Logs in Elasticsearch oder Loki, Traces bei einem Anbieter, den jemand vor zwei Jahren ausgewählt hat, und jedes dieser Systeme bringt eigene Agenten, eigene Bibliotheken im Anwendungscode und eigene Namen für dasselbe Feld mit. Sobald das Backend gewechselt werden soll, weil der Vertrag ausläuft oder die Datenmenge zu teuer wird, muss der Anwendungscode angefasst werden. Genau diese Bindung ist der Grund, warum viele Teams einen Wechsel jahrelang vor sich herschieben.

Der dritte Punkt ist der teuerste. Observability-Daten wachsen schneller als das Geschäft, weil jede neue Instanz, jeder neue Kennwertname und jedes zusätzliche Attribut die Datenmenge vervielfacht. Ein einziges Attribut mit hoher Kardinalität, etwa eine Kundennummer als Metrik-Label, kann eine Zeitreihendatenbank innerhalb von Stunden unbenutzbar machen. Wer Observability einführt, ohne von Anfang an Sampling, Aufbewahrung und Kardinalität festzulegen, bekommt die Rechnung im nächsten Quartal und schaltet dann pauschal ab, statt gezielt zu begrenzen.

Miniatur-Szene: Treppe aus drei Stufen hinauf zu einer schwebenden Cloud, Laptop und Wegweiser

Vom ersten Span bis zum begrenzten Datenstrom

  1. 01 Dienst mit Agent instrumentieren, ohne Code zu ändern
  2. 02 Collector als zentrale Drehscheibe daneben stellen
  3. 03 Attribute vereinheitlichen und sensible Felder entfernen
  4. 04 Sampling und Aufbewahrung je Signalart festlegen
  5. 05 Backend anbinden, austauschbar halten, Alarme ergänzen
Was du mitnimmst

Was OpenTelemetry löst und was es nicht löst

OpenTelemetry ist kein Monitoringprodukt, sondern die Schicht davor: ein einheitliches Format, eine einheitliche Instrumentierung und ein Vermittler, der die Daten dorthin schickt, wo du sie auswerten willst. Die Auswertung selbst machen weiterhin Prometheus, Grafana, Loki, Tempo oder ein kommerzielles Backend.

Drei Signale, ein Protokoll

Traces, Metriken und Logs verlassen die Anwendung im selben Format, über OTLP an Port 4317 für gRPC oder 4318 für HTTP. Der entscheidende Gewinn ist nicht das Protokoll, sondern die gemeinsame Kennzeichnung: derselbe Dienstname, dieselbe Umgebung und dieselbe Trace-Kennung an allen drei Signalen. Erst dadurch springst du vom langsamen Trace direkt in die Logzeilen desselben Aufrufs.

Automatische Instrumentierung als Startpunkt

Für Java, .NET, Python, Node.js und PHP gibt es Agenten und Startwrapper, die verbreitete Rahmenwerke, HTTP-Clients und Datenbanktreiber ohne Codeänderung erfassen. Damit bekommst du an einem Nachmittag brauchbare Traces über die gesamte Aufrufkette. Eigene Spans für fachliche Schritte ergänzt du danach, und nur dort, wo die automatische Erfassung nichts sieht, etwa in Hintergrundjobs und beim Lesen aus Warteschlangen.

Der Collector entkoppelt dich vom Backend

Der OpenTelemetry Collector nimmt Daten entgegen, verarbeitet sie und verteilt sie an ein oder mehrere Ziele. Weil die Anwendungen nur den Collector kennen, wechselst du das Backend durch eine geänderte Konfigurationszeile statt durch ein Rollout aller Dienste. Gleichzeitig ist der Collector die Stelle, an der du Attribute vereinheitlichst, sensible Felder entfernst und Datenmengen begrenzt.

Sampling entscheidet über die Rechnung

Kopfbasiertes Sampling verwirft direkt in der Anwendung einen festen Anteil der Traces und kostet fast nichts. Schwanzbasiertes Sampling im Collector entscheidet erst, wenn ein Trace vollständig ist, und behält gezielt Fehler und langsame Aufrufe. Die übliche Kombination lautet: alles behalten, was fehlschlägt oder länger als eine Schwelle dauert, vom Rest eine kleine Stichprobe.

Semantische Konventionen sparen späteres Aufräumen

OpenTelemetry legt Attributnamen fest, etwa service.name, deployment.environment.name oder http.request.method. Wer sie von Anfang an verwendet, kann Dashboards und Alarme über Teams hinweg wiederverwenden und Backends ohne Umbenennung tauschen. Eigene Attribute bekommen ein festes Präfix, damit sie später nicht mit neuen Standardfeldern kollidieren.

Was OpenTelemetry nicht ersetzt

Speicher, Abfragesprache, Dashboards und Alarmierung bleiben Aufgabe des Backends. OpenTelemetry nimmt dir die Entscheidung für Tempo, Jaeger oder ein kommerzielles Produkt nicht ab, es macht die Entscheidung nur umkehrbar. Und es ersetzt kein Betriebskonzept: Wer keine Alarmschwellen definiert, hat mit Traces genauso wenig Überblick wie vorher, nur mehr Daten.

Tutorial

Von der ersten instrumentierten Anwendung bis zum begrenzten Datenstrom

Die Instrumentierung ist bei den meisten Sprachen an einem Nachmittag erledigt, der eigentliche Aufwand steckt in der Frage, wie viele Daten du dauerhaft bezahlen willst. Deshalb kommt der Collector früh ins Spiel, denn er begrenzt die Menge und hält das Backend austauschbar. Der Ablauf folgt dieser Logik, von der ersten Anwendung ohne Codeänderung über den Collector und das Ausrollen in Kubernetes bis zur Begrenzung von Datenmenge und Kosten.

01

Schritt 1: Eine Anwendung ohne Codeänderung instrumentieren

Der schnellste Weg zu belastbaren Traces führt über die automatische Instrumentierung. Sie hängt sich beim Start an das Laufzeitsystem und erfasst HTTP-Aufrufe, Datenbankzugriffe und Warteschlangen, ohne dass eine Zeile Anwendungscode geändert wird.

Gesteuert wird alles über Umgebungsvariablen. Der wichtigste Wert ist der Dienstname, denn er taucht später in jedem Trace, jeder Metrik und jeder Logzeile auf. Vergib ihn einmal richtig und nach einem festen Schema, sonst heißen drei Dienste später unknown_service und niemand kann Daten mehr zuordnen.

Java-Agent laden und über Umgebungsvariablen steuern
curl -sLO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar

export OTEL_SERVICE_NAME="checkout-api"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment.name=prod,service.namespace=shop"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://otel-collector:4317"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_TRACES_SAMPLER="parentbased_traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"

java -javaagent:./opentelemetry-javaagent.jar -jar checkout.jar

Der Sampler parentbased_traceidratio entscheidet in der Anwendung und behält hier zehn Prozent der Traces. Wichtig ist das Präfix parentbased: Nur damit übernimmt ein Dienst die Entscheidung des Aufrufers, sonst reißt der Trace mitten in der Kette ab.

Dasselbe für Python und Node.js
# Python: Instrumentierung als Wrapper vor den Prozess haengen
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install

OTEL_SERVICE_NAME=orders-api \
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
  opentelemetry-instrument python app.py

# Node.js: Registrierung vor dem eigenen Code laden
npm install @opentelemetry/auto-instrumentations-node
node --require @opentelemetry/auto-instrumentations-node/register server.js

opentelemetry-bootstrap -a install liest die installierten Pakete und ergänzt die passenden Instrumentierungen. Führe den Befehl nach jedem größeren Abhängigkeitsupdate erneut aus, sonst fehlen neu hinzugekommene Bibliotheken in den Traces und du suchst die Lücke im Collector.

02

Schritt 2: Den Collector als Drehscheibe aufsetzen

Der Collector ist das Stück, das aus einer Bastellösung einen Betrieb macht. Er puffert, vereinheitlicht, filtert und verteilt, und er ist die einzige Komponente, die dein Backend überhaupt kennt.

/etc/otelcol-contrib/config.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
  resource:
    attributes:
      - key: deployment.environment.name
        value: prod
        action: upsert
  attributes:
    actions:
      - key: http.request.header.authorization
        action: delete
  batch:
    send_batch_size: 8192
    timeout: 5s

exporters:
  otlp/tempo:
    endpoint: tempo:4317
    tls:
      insecure: true
  otlphttp/prometheus:
    endpoint: http://prometheus:9090/api/v1/otlp
  debug:
    verbosity: basic

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, resource, attributes, batch]
      exporters: [otlp/tempo]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, resource, batch]
      exporters: [otlphttp/prometheus]

Die Reihenfolge unter processors ist die Verarbeitungsreihenfolge. memory_limiter gehört immer an den Anfang, batch immer ans Ende. Prometheus nimmt OTLP erst entgegen, wenn es mit --web.enable-otlp-receiver gestartet wurde, sonst bekommst du dauerhaft Fehler mit dem Statuscode 404.

Die drei Bausteine einer Collector-Pipeline

BausteinWofür er zuständig istTypische Vertreter
ReceiverNimmt Daten entgegen oder holt sie aktiv abotlp, filelog, hostmetrics, prometheus, kubeletstats
ProcessorVerändert, reichert an, filtert, begrenztmemory_limiter, batch, resource, attributes, filter, transform, k8sattributes, tail_sampling
ExporterSchickt die Daten an ein Zielotlp, otlphttp, prometheusremotewrite, debug

Betreibe den Collector zweistufig, sobald mehr als eine Handvoll Dienste liefert: Ein Agent je Knoten sammelt lokal ein und puffert bei Ausfällen, ein Gateway als eigenständiges Deployment übernimmt Sampling, Anreicherung und den Versand nach außen. Das Gateway ist der Ort, an dem du später Kosten begrenzt, und es ist zugleich die einzige Komponente mit Verbindung nach draußen, was in Umgebungen ohne Internetzugang zur Voraussetzung wird.

03

Schritt 3: In Kubernetes ausrollen

In Kubernetes übernimmt der OpenTelemetry Operator die lästigen Teile. Er verwaltet Collector-Instanzen als eigene Ressource und schleust die Instrumentierung über eine Annotation in die Pods ein.

Operator samt Voraussetzung installieren
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
kubectl -n cert-manager rollout status deploy/cert-manager-webhook

kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml
kubectl -n opentelemetry-operator-system get pods
kubectl api-resources | grep opentelemetry

Der Operator braucht cert-manager für seine Webhooks. Fehlt er, werden die neuen Ressourcen zwar angelegt, aber nie verarbeitet, und im Log des Operators steht ein Zertifikatsfehler statt einer verständlichen Meldung.

instrumentation.yaml
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: standard
  namespace: shop
spec:
  exporter:
    endpoint: http://otel-gateway-collector.observability.svc:4317
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "0.1"
---
# Anwendung markieren, der Operator haengt den Agenten beim naechsten Start ein:
# kubectl patch deployment checkout -n shop --type=merge -p \
#   '{"spec":{"template":{"metadata":{"annotations":
#      {"instrumentation.opentelemetry.io/inject-java":"standard"}}}}}'

Die Annotation gehört an die Pod-Vorlage, nicht an das Deployment selbst. Zweiter häufiger Fehler: Der Wert muss der Name der Instrumentation-Ressource sein, sobald diese in einem anderen Namensraum liegt, ein schlichtes true greift dann nicht.

04

Schritt 4: Datenmenge und Kosten begrenzen

Observability-Kosten steigen nicht linear, sondern sprunghaft. Die drei Stellschrauben sind Sampling, Kardinalität und Aufbewahrung, und alle drei gehören konfiguriert, bevor die erste Rechnung kommt.

Schwanzbasiertes Sampling und Filter im Gateway
processors:
  tail_sampling:
    decision_wait: 10s
    num_traces: 100000
    policies:
      - name: fehler-immer-behalten
        type: status_code
        status_code:
          status_codes: [ERROR]
      - name: langsame-behalten
        type: latency
        latency:
          threshold_ms: 800
      - name: rest-stichprobe
        type: probabilistic
        probabilistic:
          sampling_percentage: 5
  filter/gesundheitschecks:
    error_mode: ignore
    traces:
      span:
        - 'attributes["http.route"] == "/healthz"'

decision_wait muss länger sein als der langsamste Aufruf, den du behalten willst, sonst entscheidet der Collector über unvollständige Traces. Schwanzbasiertes Sampling setzt außerdem voraus, dass alle Spans eines Traces dieselbe Gateway-Instanz erreichen, also Lastverteilung nach Trace-Kennung statt zufällig.

Vor dem Produktivstart festlegen

  • Aufbewahrungsfrist je Signalart getrennt setzen, etwa dreißig Tage für Metriken, vierzehn für Logs, sieben für Traces.Traces sind das teuerste Signal und werden fast nur in den ersten Tagen nach einer Störung gelesen. Eine einheitliche Frist für alle drei Signale bezahlt Speicher für Daten, die niemand mehr abfragt.
  • Erlaubte Attribute an Metriken auf eine feste Positivliste begrenzen.Ohne Positivliste ergänzt früher oder später jemand ein Attribut mit hoher Kardinalität. Der Ausfall trifft dann die Zeitreihendatenbank und alle Teams, nicht den Verursacher.
  • Authentifizierungsheader, Cookies und Nutzdaten im Collector löschen.Instrumentierungsbibliotheken erfassen mehr, als man erwartet. Landen Zugangsdaten oder personenbezogene Daten im Trace-Speicher, entsteht ein DSGVO-Problem in einem System, das kein gezieltes Löschen einzelner Datensätze vorsieht.
  • Grenzwerte für Speicher und Warteschlange des Collectors setzen und überwachen.Ein Collector ohne memory_limiter stirbt unter Last am Speichermangel und reißt genau in dem Moment die Beobachtbarkeit mit, in dem du sie brauchst.
  • Die eigenen Kennwerte des Collectors in die Alarmierung aufnehmen.Verworfene Spans und abgelehnte Batches sind das erste Anzeichen für eine überlastete Pipeline. Ohne Alarm bemerkt ihr den Datenverlust erst, wenn im Störungsfall ein Trace fehlt.
05

Schritt 5: Backend anbinden und austauschbar halten

Die letzte Etappe entscheidet, ob ihr in einem Jahr noch wechseln könnt. Solange nur der Collector das Ziel kennt, ist ein Wechsel eine Konfigurationsänderung und kein Projekt.

Zwei Ziele parallel bespielen, um sie zu vergleichen
exporters:
  otlp/alt:
    endpoint: tempo.observability.svc:4317
    tls:
      insecure: true
  otlphttp/neu:
    endpoint: https://otlp.anbieter.example
    headers:
      authorization: ${env:OTLP_TOKEN}

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, k8sattributes, tail_sampling, batch]
      exporters: [otlp/alt, otlphttp/neu]

Ein Doppelversand über zwei bis vier Wochen ist der ehrlichste Test für ein neues Backend, weil beide Systeme dieselben Daten sehen. Rechne dabei mit doppeltem ausgehendem Datenverkehr, der bei Cloud-Anbietern je Gigabyte abgerechnet wird und in dieser Zeit der größere Kostenblock sein kann als das Backend selbst.

Prüfe bei der Auswahl drei Dinge, die in Produktvergleichen selten stehen: ob das Backend OTLP direkt entgegennimmt oder doch eine eigene Bibliothek verlangt, wonach es abrechnet, also nach aufgenommenen Gigabyte, nach Zeitreihen oder nach Hosts, und wo die Daten liegen. Für eine Verarbeitung in der EU brauchst du eine Region in der EU und einen Auftragsverarbeitungsvertrag, sonst wird die Werkzeugwahl zum Datenschutzthema. Wer diese Fragen früh stellt, spart sich die Diskussion, die sonst ein Jahr später bei der Analyse der Cloud-Kosten geführt wird.

Wissen prüfen

Teste dich und finde deinen Weg

Bevor du einen Kurs buchst, lohnt sich eine ehrliche Standortbestimmung. Die Tests sind kostenlos und ohne Anmeldung.

Gut zu wissen

Häufige Fragen zu Observability und OpenTelemetry

Noch etwas offen? Wir sind ohne Warteschleife für dich da.

Frag uns direkt
Brauchen wir Traces, wenn Prometheus und Loki bereits laufen?
Solange eine Anfrage einen einzigen Dienst berührt, reichen Metriken und Logs. Sobald sie über drei oder mehr Dienste läuft, beantworten sie die entscheidende Frage nicht mehr: Welcher Schritt hat die Zeit gekostet. Traces schließen genau diese Lücke, und sie tun es für einzelne Aufrufe statt im Durchschnitt. Der pragmatische Weg ist, Prometheus und Loki zu behalten und OpenTelemetry als Zulieferer davorzusetzen. Damit gewinnt ihr die Trace-Sicht und die gemeinsame Kennzeichnung aller drei Signale, ohne das abzureißen, was heute funktioniert.
Lässt sich OpenTelemetry ohne Änderung am Anwendungscode einführen?
Für Java, .NET, Python, Node.js und PHP ja, über Agenten oder Startwrapper, die verbreitete Rahmenwerke, HTTP-Clients und Datenbanktreiber selbstständig erfassen. In Kubernetes übernimmt der Operator sogar das Einhängen per Annotation. Go ist die Ausnahme, weil dort kompiliert wird, dafür braucht es entweder eBPF-basierte Erfassung oder Bibliotheksaufrufe im Code. Ohne Codeänderung kommst du weit genug für eine vollständige Aufrufkette. Fachliche Spans, etwa um einen Bezahlvorgang oder einen Importlauf zu messen, verlangen danach doch ein paar Zeilen, aber nur an wenigen Stellen.
Wie viel Leistung kostet die Instrumentierung?
Bei automatischer Instrumentierung mit moderatem Sampling liegt der Zusatzaufwand üblicherweise im niedrigen einstelligen Prozentbereich an Rechenzeit, dazu kommt etwas Arbeitsspeicher für Puffer. Spürbar wird es in zwei Fällen: bei sehr kurzen, sehr häufigen Aufrufen und bei vollständigem Sampling ohne Begrenzung. Miss es selbst, statt zu schätzen, indem du einen Dienst mit und ohne Agent unter gleicher Last vergleichst. Der größere Kostenblock ist ohnehin nicht die Laufzeit, sondern die Datenmenge im Backend und der ausgehende Datenverkehr dorthin.
Wie lange dürfen wir Traces aufbewahren?
Technisch bestimmt das euer Budget, rechtlich euer Löschkonzept. Traces und Logs enthalten regelmäßig personenbezogene Daten, etwa IP-Adressen, Benutzerkennungen oder Inhalte aus Anfragen, und fallen damit unter die DSGVO. Sinnvoll ist eine kurze Frist von sieben bis vierzehn Tagen für Traces, weil sie fast nur unmittelbar nach einer Störung gelesen werden, und eine getrennte, längere Frist für aggregierte Metriken ohne Personenbezug. Entferne sensible Felder im Collector, bevor sie gespeichert werden. Einzelne Spans nachträglich zu löschen, ist in den meisten Backends nicht vorgesehen.
Womit fangen wir an, wenn vierzig Dienste im Betrieb sind?
Nicht mit einer Inventur, sondern mit dem Weg durch das System, der am häufigsten in Störungsmeldungen auftaucht. Instrumentiere den Einstiegspunkt und seine direkten Nachbarn, stelle den Collector daneben und schicke die Daten in ein Backend, das ihr ohnehin schon betreibt. Nach zwei Wochen habt ihr eine belastbare Aussage darüber, ob sich der Aufwand lohnt. Erst danach lohnt die Vereinheitlichung: gemeinsame Attributnamen, ein zentrales Gateway, verbindliche Sampling-Regeln. Wer umgekehrt vorgeht, verbringt ein Quartal mit Standards, bevor der erste Trace jemandem geholfen hat.

Zuletzt geprüft am 26. Juli 2026.

Das sagen Teilnehmer

Echte Stimmen aus unseren IT-Kursen

Sehr intensiver Lehrgang, hat mich für meine Arbeit ein gutes Stück voran gebracht.
Rückmeldung aus dem Kurs „Monitoring mit Prometheus und Grafana - Grundkurs“
Sehr kompetent, kurzweilig, hat mich nochmals sehr weitergebracht in meinem täglichen doing.
Rückmeldung aus dem Kurs „AZ-400 Training: Designing and Implementing Microsoft DevOps solutions (AZ-400T00-A)“
Persönlich für dich da

Deine Ansprechpartner

Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Hilft dir, aus dem Cloud-Programm den passenden Kurs oder Lernpfad zu finden.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant mit dir Inhouse-Trainings, die exakt auf eure Systemlandschaft und Distributionen zugeschnitten sind.

Nächster Schritt

Observability aufbauen, ohne bei null anzufangen

Die Bausteine lassen sich einzeln lernen: Metriken und Alarmierung im Kurs Monitoring mit Prometheus und Grafana, Logauswertung mit Grafana Loki oder mit Elasticsearch und Kibana, den Unterbau im Kubernetes Grundkurs. Wer den gesamten Betriebsprozess einmal in einer Cloud-Umgebung durchspielen will, findet ihn im Kurs zum Google Cloud Professional Cloud DevOps Engineer. Alle Kurse laufen Live-Online oder in Präsenz. Wenn du unsicher bist, womit dein Team anfangen sollte, sprich uns an, wir ordnen das anhand eurer Ausgangslage ein.