Observability
Ein Nutzer meldet: „Die Bestellung hängt.“ Im Monolithen gab es einen Stacktrace – bei zwanzig Diensten gibt es zwanzig Logdateien. Wie Logs, Metriken und Traces zusammenspielen, warum der Durchschnitt lügt und was ein Fehlerbudget ist.
Observability (Beobachtbarkeit) heißt: Man kann aus den Daten, die ein laufendes System nach außen gibt, verstehen, was in ihm vorgeht – auch bei Fehlern, an die vorher niemand gedacht hat. Die drei Grundarten dieser Daten sind Logs (einzelne Ereignisse), Metriken (Zahlen über die Zeit) und Traces (der Weg einer Anfrage durch alle Dienste).
Klassisches Monitoring beantwortet bekannte Fragen: Ist die CPU voll? Observability soll auch unbekannte beantworten: Warum sind nur Bestellungen mit Gutschein aus Österreich langsam? Der heutige Standard, um alle drei Datenarten zu erzeugen, ist OpenTelemetry.
Logs, Metriken, Traces
Was ist passiert?
Einzelne Ereignisse mit Zeitstempel und Details: „Zahlung für Bestellung 4711 abgelehnt, Grund: Limit“. Reich an Kontext, aber teuer in der Menge und nur durchsuchbar, wenn sie strukturiert sind – als JSON-Felder statt als Fließtext.
Wie viel, wie schnell?
Zahlen über die Zeit: Anfragen pro Sekunde, Fehlerquote, Antwortzeiten, Speicherverbrauch. Billig zu speichern, ideal für Dashboards und Alarme – aber zusammengefasst, ohne den einzelnen Fall.
Wo ging die Zeit hin?
Der Weg einer einzelnen Anfrage durch alle Dienste, als Baum von Spans mit Start und Dauer. Zeigt, welcher Aufruf langsam war oder fehlschlug – das Werkzeug für Microservices.
Die Stärke entsteht durch die Verbindung: Eine Metrik zeigt, dass etwas schiefläuft – die Antwortzeit steigt. Ein Trace zeigt, wo – im Zahlungsdienst. Die Logs dieses Traces zeigen, warum – Zeitüberschreitung beim Zahlungsanbieter. Damit das funktioniert, trägt jede Logzeile die Trace-ID der Anfrage, zu der sie gehört.
Verteiltes Tracing
Beim ersten Dienst bekommt eine Anfrage eine Trace-ID. Bei jedem weiteren Aufruf wird sie mitgeschickt – über HTTP im Header traceparent (W3C-Standard), über Nachrichten in deren Headern. Jeder Dienst meldet seine Spans an einen Sammler, und daraus entsteht dieses Wasserfalldiagramm. Wähle ein Problem:
Warum der Durchschnitt lügt
Antwortzeiten sind fast nie normalverteilt: Die meisten Anfragen sind schnell, ein paar sehr langsam. Der Durchschnitt verwischt das. Deshalb misst man Perzentile: p95 = 500 ms heißt, 95 % der Anfragen waren schneller als 500 ms. Schieb den Anteil langsamer Anfragen hoch:
Gerade die langsamen Anfragen sind wichtig: Oft sind es die Kunden mit dem größten Warenkorb. Und wer bei einem Seitenaufbau zwanzig Dienste fragt, trifft fast sicher auf einen langsamen – das p99 eines einzelnen Dienstes wird zum Normalfall der Seite.
SLOs und Fehlerbudget
Wie zuverlässig muss ein Dienst sein? 100 % ist unerreichbar und unbezahlbar. Stattdessen legt man ein Service Level Objective fest, etwa: „99,9 % der Anfragen innerhalb von 30 Tagen erfolgreich und schneller als 300 ms.“ Was zu 100 % fehlt, ist das Fehlerbudget – es darf ausgegeben werden, für Deployments, Experimente, Ausfälle.
Das Budget ist ein Werkzeug für Entscheidungen: Ist noch viel übrig, darf das Team schneller ausliefern und mehr riskieren. Ist es aufgebraucht, hat Stabilität Vorrang. Und es bestimmt die Alarme: Statt bei jeder CPU-Spitze zu wecken, schlägt man Alarm, wenn das Budget gefährlich schnell verbraucht wird – also wenn Nutzer tatsächlich etwas merken. Zu viele Alarme sind gefährlicher als zu wenige: Wer nachts ständig umsonst geweckt wird, ignoriert irgendwann auch den echten.
Für Entwickler übersetzt
// Logs: SLF4J mit Platzhaltern – Trace-ID kommt automatisch über den MDC dazu,
// wenn Micrometer Tracing oder der OpenTelemetry-Agent aktiv ist
private static final Logger log = LoggerFactory.getLogger(BestellService.class);
log.info("Bestellung angelegt id={} positionen={}", b.id(), b.positionen().size());
// Metriken: Micrometer – Zähler und Zeitmesser, mit Tags zum Aufschlüsseln
Counter.builder("bestellungen").tag("zahlart", zahlart).register(registry).increment();
Timer.builder("zahlung.dauer")
.publishPercentiles(0.5, 0.95, 0.99)
.register(registry)
.record(() -> zahlung.ausfuehren(b));
// Traces: oft ganz ohne Code – der Agent instrumentiert HTTP, JDBC, Kafka …
// java -javaagent:opentelemetry-javaagent.jar -Dotel.service.name=bestellung -jar app.jar| Baustein | Rolle |
|---|---|
| OpenTelemetry | herstellerneutraler Standard und Bibliotheken für Traces, Metriken und Logs; der Java-Agent instrumentiert gängige Bibliotheken automatisch |
| Micrometer | Metrik- und Tracing-Fassade in Spring Boot – „SLF4J für Metriken“; Actuator stellt die Werte bereit, etwa für Prometheus |
| Prometheus | holt Metriken regelmäßig ab, speichert sie als Zeitreihen und wertet Alarmregeln aus |
| Grafana | Dashboards über Metriken, Logs und Traces |
| Jaeger, Tempo, Zipkin | speichern Traces und zeigen sie als Wasserfall |
| Loki, Elasticsearch | sammeln und durchsuchen Logs |
Ein Fallstrick bei Metriken ist die Kardinalität: Jede Kombination von Tag-Werten ist eine eigene Zeitreihe. Ein Tag zahlart mit fünf Werten ist harmlos – ein Tag kundenId mit einer Million Werten legt das Metriksystem lahm. Für Einzelfälle sind Logs und Traces da.