Observability in Produktion: CloudWatch, OpenTelemetry und Grafana

Foto von Frederic Köberl auf Unsplash
Ein Nutzer meldet, die App sei langsam. Auf dem Dashboard ist alles grün. Die CPU ist normal, im Log steht kein Fehler, der Health-Check antwortet brav. Trotzdem dauert ein bestimmter Request acht Sekunden. Ohne Traces ist das eine Suche im Dunkeln, mit ein paar SSH-Sessions und viel Raten. Mit Traces ist es ein Blick: ein N-plus-1-Query in einem selten genutzten Endpoint, der unter Last erst sichtbar wird.
Observability ist nicht das Dashboard, das man baut. Es ist die Fähigkeit, eine Frage zu beantworten, die man vorher nicht gestellt hat. Ein Dashboard zeigt, was man erwartet hat. Ein Incident ist fast immer das, was man nicht erwartet hat. Drei Säulen liefern die Antwort: Logs sagen, was passiert ist, Metriken sagen, wie viel und wie oft, und Traces sagen, wo im System die Zeit verloren geht.
2026 hat sich auf AWS einiges verschoben, das die Entscheidung leichter macht. OpenTelemetry hat sich als Standard durchgesetzt, und AWS hat die native Integration nachgezogen. Dieser Artikel zeigt den AWS-nativen Weg, den OpenTelemetry-Weg und wann welcher passt. Stand ist Juni 2026, Region eu-central-1 als Referenz.
Die drei Säulen: Logs, Metriken, Traces
Die drei Säulen beantworten unterschiedliche Fragen, und keine ersetzt die andere.
Logs sagen, was passiert ist, mit Kontext. Sie gehören strukturiert als JSON, nicht als Freitext, sonst sind sie nicht durchsuchbar. Ein Log mit Feldern für Request-ID, User-ID und Dauer lässt sich filtern, ein zusammengeklebter String nicht.
Metriken sind aggregierte Zahlen über Zeit. Request-Rate, Fehlerrate, Latenz-Perzentile, Queue-Tiefe. Sie sind billig zu speichern und schnell zu aggregieren, aber sie haben kein Detail. Eine Metrik sagt, dass die Fehlerrate auf fünf Prozent gestiegen ist, nicht warum.
Traces zeigen den Weg eines einzelnen Requests durch alle Services und Abhängigkeiten, mit der Zeit pro Span. Das ist die Säule, die "warum ist genau dieser Request langsam" beantwortet, und die in den meisten Mittelstand-Setups fehlt.
Der eigentliche Wert liegt in der Verbindung. Ein Alarm auf einer Metrik führt zum Trace, der Trace führt zum Log mit derselben Trace-ID. Erst wenn die drei zusammenhängen, wird aus drei Datenquellen ein Werkzeug. Genau diese Verbindung war früher Handarbeit und ist mit OpenTelemetry zum Standard geworden.
Der Standard 2026: OpenTelemetry
Was OpenTelemetry löst
OpenTelemetry ist ein herstellerneutraler Standard, um Logs, Metriken und Traces zu erzeugen, einzusammeln und zu exportieren. Der Punkt ist die Trennung: Man instrumentiert die App einmal nach dem Standard, und das Backend ist eine Konfigurationsfrage, keine Code-Entscheidung. Wer heute mit OpenTelemetry instrumentiert, kann morgen von CloudWatch zu Grafana oder Datadog wechseln, ohne eine Zeile Anwendungscode anzufassen.
X-Ray im Maintenance-Mode
Das ist kein theoretischer Vorteil mehr. Die X-Ray-SDKs und der X-Ray-Daemon sind 2026 offiziell im Maintenance-Mode. AWS empfiehlt die Migration auf AWS Distro for OpenTelemetry, kurz ADOT, die AWS-eigene Distribution des OpenTelemetry-Collectors. Wer ein neues Projekt aufsetzt, instrumentiert nicht mehr mit dem X-Ray-SDK, sondern mit OpenTelemetry. Wer ein bestehendes hat, plant die Migration.
Was CloudWatch 2026 nachgezogen hat
AWS hat die native Seite kräftig ausgebaut. CloudWatch nimmt jetzt OpenTelemetry über alle drei Säulen entgegen, per OTLP, dem OpenTelemetry-Protokoll. Ein Protokoll für Logs, Metriken und Traces. Der praktisch wichtigste Teil: OTLP-Metriken erlauben bis zu 150 Labels, gegenüber dem Limit von 30 Dimensionen bei klassischen CloudWatch-Custom-Metrics. Genau dieser Unterschied macht hochkardinale Kubernetes- und Microservice-Workloads überhaupt erst handhabbar. Dazu kommt PromQL-Unterstützung, sodass man CloudWatch-Metriken mit der Prometheus-Abfragesprache abfragen kann.
Der ADOT-Collector als Herzstück
Die Pipeline
Der Collector ist der Mittelsmann zwischen App und Backend. Die App schickt ihre Telemetrie als OTLP an den Collector, über gRPC auf Port 4317 oder HTTP auf Port 4318. Der Collector verarbeitet sie und exportiert sie weiter. Die App selbst kennt das Backend nicht, sie kennt nur den Collector.
Die Pipeline hat drei Stufen. Ein Receiver nimmt die OTLP-Daten entgegen. Ein oder mehrere Processor batchen, filtern und sampeln. Ein oder mehrere Exporter schicken die Daten an das Ziel, das kann CloudWatch sein, Amazon Managed Prometheus, oder beides parallel. Eine minimale Collector-Config sieht so aus:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 10s
exporters:
awsemf:
namespace: laravel-production
log_group_name: /ecs/laravel/metrics
prometheusremotewrite:
endpoint: https://aps-workspaces.eu-central-1.amazonaws.com/workspaces/ws-xxxx/api/v1/remote_write
auth:
authenticator: sigv4auth
service:
pipelines:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [awsemf, prometheusremotewrite]Sidecar auf Fargate, DaemonSet auf EKS
Wo der Collector läuft, hängt von der Plattform ab. Auf Fargate läuft er als Sidecar-Container in derselben Task-Definition wie die App. Die App schickt an localhost:4317, der Sidecar exportiert nach außen. Auf EKS läuft der Collector als DaemonSet, also ein Collector-Pod pro Node, oder als zentrales Deployment für aggregierende Aufgaben.
Warum überhaupt der Collector und nicht direkt aus der App exportieren? Weil Sampling, Filtering und Batching an eine Stelle gehören, nicht in jede App und jede Sprache. Wer das Backend wechselt, ändert eine Collector-Config und deployt den Sidecar neu, statt jede App anzufassen. Der Sidecar im Fargate-Setup ist ein zusätzlicher Container in der Task-Definition, mehr nicht.
Eine Laravel-App instrumentieren
Auto-Instrumentierung
Der angenehme Teil: Eine Laravel-App muss man nicht von Hand mit Spans bestücken. Das Paket opentelemetry-auto-laravel erfasst HTTP-Requests, Eloquent-Queries, Redis-Operationen und Queue-Jobs automatisch, ohne dass man pro Route oder pro Model Code ändert. Man installiert das Composer-Paket plus die OpenTelemetry-PHP-Extension und konfiguriert den Rest über Umgebungsvariablen:
composer require open-telemetry/opentelemetry-auto-laravel# Umgebungsvariablen, in der Task-Definition gesetzt
OTEL_PHP_AUTOLOAD_ENABLED=true
OTEL_SERVICE_NAME=laravel-web
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobufDer OTLP-Endpoint zeigt auf den Collector-Sidecar auf localhost. Ab da fließen Traces für jeden Request, jede Query und jeden Job, ohne weiteren Code.
Logs und Traces verbinden
Das ist der Punkt, der den Unterschied im Incident macht. Mit dem OTLP-Log-Driver injiziert Laravel die aktuelle Trace-ID automatisch in den Log-Kontext. Ein Fehler-Log trägt dann die Trace-ID des Requests, der ihn ausgelöst hat. Im Incident springt man vom langsamen oder fehlerhaften Trace direkt zum passenden Log, ohne nach Zeitstempeln zu suchen. Was man darüber hinaus von Hand ergänzt, sind Custom-Spans für die eigenen kritischen Pfade, etwa einen externen API-Call oder eine teure Berechnung, die die Auto-Instrumentierung nicht kennt.
Der AWS-native Weg: CloudWatch
Container Insights und Logs Insights
Für viele Setups ist CloudWatch allein die richtige Wahl. CloudWatch Logs mit Logs Insights erlaubt Ad-hoc-Abfragen über strukturierte Logs, ohne ein zweites System. Eine Abfrage nach der Fehlerrate pro Endpoint ist eine Zeile:
fields @timestamp, route, status
| filter status >= 500
| stats count() as errors by route
| sort errors desc
Container Insights liefert die Container-Ebene für ECS und EKS, und seit 2026 mit OpenTelemetry- und Prometheus-Metriken, abfragbar per PromQL. Damit verschwimmt die alte Grenze zwischen "CloudWatch-Welt" und "Prometheus-Welt", denn dieselben PromQL-Abfragen funktionieren auf beiden Seiten.
Application Signals
Der vielleicht unterschätzteste Baustein ist Application Signals. Es liefert APM und SLOs aus Standard-OpenTelemetry-Instrumentierung, in vielen Fällen ohne eine einzige Code-Änderung, nur über eine Umgebungsvariable:
OTEL_AWS_APPLICATION_SIGNALS_ENABLED=trueDamit bekommt man eine Service-Map, Latenz- und Fehlerraten pro Service und SLO-Tracking. Für ein Mittelstand-Team, das keine eigene SRE-Abteilung hat, ist das eine Menge Wert für sehr wenig Aufwand. Auf diesen Alarmen baut auch das automatische Rollback beim Deploy auf, das im kommenden Zero-Downtime-Artikel dran ist.
Wann CloudWatch allein reicht: bei der Mehrheit der Mittelstand-Setups. Eine bis wenige Services, ein Team, kein bestehender Grafana-Stack. Man spart sich zwei zusätzliche Systeme und deren Betrieb.
Der OpenTelemetry-Weg: Prometheus und Grafana
Amazon Managed Prometheus
Wer mehr braucht, kombiniert ADOT mit Amazon Managed Prometheus für die Metriken. AMP ist pay-per-use, ohne Vorab-Commit. Stand Juni 2026 kostet es rund 0,003 USD pro Million ingestierter Samples plus Query- und Collector-Kosten. PromQL ist nativ, und wer aus der Kubernetes-Welt kommt, fühlt sich sofort zu Hause. Der ADOT-Collector exportiert die Metriken per Remote-Write an AMP, die Logs gehen parallel nach CloudWatch.
Amazon Managed Grafana
Für die Visualisierung kommt Amazon Managed Grafana dazu. Die Abrechnung läuft pro aktivem Nutzer pro Workspace, Stand Juni 2026 rund 9 USD pro Editor und 5 USD pro Viewer pro Monat. Grafana visualisiert AMP-Metriken, CloudWatch-Logs und Traces in einer Oberfläche, und wer bereits Grafana-Dashboards aus anderen Projekten hat, nutzt sie weiter.
Wann sich das lohnt: bei vorhandenem Grafana-Know-how und bestehenden Dashboards, bei hochkardinalen Metriken, bei mehreren Datenquellen, die in einer Sicht zusammenlaufen sollen, oder bei einer Multi-Cloud-Strategie, die nicht an CloudWatch gebunden sein will. Die ehrliche Kehrseite: mehr Mächtigkeit bedeutet mehr bewegliche Teile. Für eine einzelne App auf einem Account ist der Grafana-Stack Overhead, den man betreibt, ohne ihn auszunutzen.
Was man tatsächlich misst
Golden Signals und RED
Telemetrie zu sammeln ist einfach. Das Richtige zu messen ist die eigentliche Arbeit. Die Golden Signals aus dem Google-SRE-Buch sind ein guter Anker: Latenz, Traffic, Fehler und Sättigung. Für request-getriebene Services fasst man sie oft als RED zusammen, also Rate, Errors und Duration. Das sind die drei Zahlen, die im Incident zuerst zählen.
Latenz misst man immer als Perzentile, nie als Mittelwert. Der Durchschnitt versteckt genau die langsamen Requests, die Nutzer spüren. Wenn 95 Prozent der Requests in 100 ms durch sind und 5 Prozent in 4 Sekunden, ist der Mittelwert unauffällig, und trotzdem hat jeder zwanzigste Nutzer ein schlechtes Erlebnis. p50, p95 und p99 zeigen das, der Durchschnitt nicht.
SLOs statt Vanity-Metrics
Ein Service-Level-Objective gibt der Alarmierung einen Sinn. "99 Prozent der Requests unter 300 ms über 30 Tage" ist ein SLO, an dem man messen kann, ob das System gut genug ist, und ab wann ein Alarm gerechtfertigt ist. Application Signals trackt SLOs nativ. Für Worker und Queues gehören Queue-Tiefe, Job-Wartezeit und die Failed-Jobs-Rate dazu, die schon im Fargate-Artikel die Grundlage fürs Autoscaling waren. Was nicht dazugehört, ist alles, was messbar ist, nur weil es messbar ist. Jede ungenutzte Metrik ist Rauschen und kostet.
Kostendisziplin
Observability frisst sich selbst, wenn man sie lässt, und das ist die direkte Brücke zu den AWS-Geldgräbern. Drei Stellschrauben halten die Kosten im Rahmen.
Trace-Sampling: Man muss nicht jeden Request tracen. Head- oder Tail-Sampling im Collector behält zum Beispiel 10 Prozent der Requests plus alle, die einen Fehler enthalten. Damit sieht man jedes Problem und zahlt nur einen Bruchteil. Log-Retention: Debug-Logs gehören nicht für immer aufbewahrt, eine sinnvolle Retention pro Log-Gruppe spart still und stetig. Metrik-Kardinalität: Hochkardinale Labels wie User-ID oder Request-ID gehören nicht in Metriken, sondern in Traces. Eine Metrik mit einem Label pro Nutzer explodiert in der Kardinalität, und bei AMP zahlt man pro Million Samples.
Der grobe Vergleich: CloudWatch ist einfach und ohne Lizenzkosten, skaliert aber bei hohem Volumen im Preis. AMP plus AMG hat Nutzer- und Sample-Kosten, ist bei großem Metrik-Volumen dafür kalkulierbarer. Datadog und vergleichbare Anbieter sind mächtiger und deutlich teurer. Für den Mittelstand ist die Reihenfolge meist klar: erst CloudWatch ausreizen, dann gezielt erweitern.
Welcher Stack für wen
Vier Fragen klären die Wahl, bevor man irgendetwas aufsetzt. Wie viele Services und Teams, jetzt und in zwölf Monaten? Gibt es bereits Grafana-Dashboards oder PromQL-Know-how im Team? Brauchen wir hochkardinale Metriken, etwa pro Tenant oder pro Kunde? Wollen wir an CloudWatch gebunden sein oder portabel bleiben?
| Profil | Empfehlung |
|---|---|
| Ein bis wenige Services, ein Team, AWS-only | CloudWatch plus Application Signals |
| Bestehender Grafana-Stack, PromQL-Know-how | ADOT zu AMP plus AMG, Logs in CloudWatch |
| Hochkardinale Per-Tenant-Metriken | AMP für Metriken, CloudWatch für Logs |
| Multi-Cloud oder Portabilität wichtig | OTel-Collector, Backend austauschbar |
| Maximale Tiefe, Budget vorhanden | Datadog oder New Relic, aber Kosten prüfen |
Das Schöne an der OpenTelemetry-Schicht: Diese Entscheidung ist nicht mehr endgültig. Wer mit OTel instrumentiert, kann den Stack später wechseln, ohne die App anzufassen.
Anti-Patterns
Logs als einzige Säule. Ohne Metriken und Traces ist jeder Incident eine Grep-Session, und Performance-Probleme bleiben unsichtbar, bis ein Nutzer anruft.
Mittelwert-Latenz. Versteckt die langsamen Requests, die zählen. Immer Perzentile.
Alles tracen ohne Sampling. Die Trace-Rechnung explodiert, der Erkenntnisgewinn steigt kaum. 10 Prozent plus alle Fehler reichen fast immer.
Hochkardinale Labels in Metriken. User-ID oder Request-ID als Metrik-Dimension sprengt Kardinalität und Kosten. Diese Information gehört in Traces.
Grafana-Stack für eine Single-Service-App. Viel bewegliche Teile, wenig Mehrwert gegenüber CloudWatch.
Dashboards bauen, die niemand ansieht. Observability ist für Incidents und SLOs, nicht für Wandschmuck im Büro.
X-Ray-SDK in neuen Projekten. Ist im Maintenance-Mode. Neue Instrumentierung geht über OpenTelemetry.
Telemetrie ohne Alarme. Daten sammeln, aber niemand wird benachrichtigt, wenn die Fehlerrate steigt. Dann merkt man den Ausfall erst, wenn der Nutzer anruft.
Fazit
Observability ist die Fähigkeit, Fragen zu beantworten, die man vorher nicht gestellt hat. Drei Säulen, verbunden über die Trace-ID, liefern sie: Logs für das Was, Metriken für das Wie viel, Traces für das Wo. Ohne die Verbindung sind es drei getrennte Datenhaufen, mit ihr ein Werkzeug.
2026 ist die Instrumentierungs-Entscheidung leichter geworden. OpenTelemetry hat sich durchgesetzt, X-Ray ist im Maintenance-Mode, und CloudWatch nimmt OTLP über alle drei Säulen entgegen. Wer mit OpenTelemetry startet, ist nicht an CloudWatch oder einen Anbieter gebunden und kann den Stack später ohne Code-Änderung wechseln. Für den Mittelstand ist CloudWatch plus Application Signals der pragmatische Default, Grafana und Prometheus kommen dazu, wenn die Anforderungen sie tragen.
Am Ende zählt nicht die Menge der gesammelten Daten, sondern die Antwort im Incident und der Alarm, der kommt, bevor der Nutzer anruft.
Sammeln Sie schon Telemetrie, aber im Incident fehlt trotzdem die Antwort, oder die CloudWatch-Rechnung wächst schneller als die Erkenntnis? Kontaktieren Sie mich für einen Observability-Audit, der Instrumentierung, Alarme und SLOs in wenigen Tagen prüft und priorisiert.
An einem IaC-Kit für Production-Laravel auf AWS arbeite ich gerade, inklusive ADOT-Collector-Sidecar und sinnvoller Basis-Alarme. Wer früh Bescheid wissen will, kann sich unverbindlich auf die Liste setzen lassen. Kein Newsletter-Dauerfeuer, nur eine Nachricht, wenn es so weit ist.