Eine Zeitreihe (Time Series) ist eine zeitlich geordnete Folge von Samples aus Zeitstempel und Wert, die zu einer Metrik und einer eindeutigen Kombination von Labels gehört. Im Monitoring bildet jede Kombination aus Metrikname und Label-Werten eine eigene Zeitreihe, die eine Zeitreihendatenbank speichert, komprimiert und über Zeitfenster abfragt.
Was ist eine Zeitreihe?
Eine Zeitreihe, englisch Time Series, ist eine Folge von Messungen derselben Größe, die über die Zeit erfasst und zeitlich geordnet gespeichert werden. In der Observability ist diese Größe eine Metrik für eine bestimmte Kombination von Dimensionen: die Anzahl der Anfragen an den Service checkout in der Region eu-central-1 mit Statuscode 500. Jede einzelne Messung ist ein Sample aus Zeitstempel und numerischem Wert.
Zeitreihen sind die Grundeinheit, in der Monitoring-Systeme Metriken speichern und abfragen. Dashboards, Alert-Regeln, SLO-Berechnungen und Anomalieerkennung arbeiten alle auf Zeitreihen.
Das Datenmodell einer Zeitreihe
Das von Prometheus bekannt gemachte Datenmodell, das mit kleinen Unterschieden auch OpenTelemetry und die meisten Metrik-Backends nutzen, besteht aus drei Teilen:
- Metrikname, etwa
http_server_requests_total, der beschreibt, was gemessen wird. - Labels (in OpenTelemetry Attribute genannt), Schlüssel-Wert-Paare wie
service="checkout"oderstatus="500". - Samples aus Zeitstempel und Wert. In Prometheus ist der Wert eine 64-Bit-Gleitkommazahl, der Zeitstempel hat Millisekundengenauigkeit.
Metrikname plus vollständiger Satz an Label-Werten bilden die Identität der Zeitreihe. Ändert sich ein einziger Label-Wert, handelt es sich um eine andere Zeitreihe:
http_server_requests_total{service="checkout", region="eu-central-1", status="200"}
http_server_requests_total{service="checkout", region="eu-central-1", status="500"}
Das sind zwei getrennte Zeitreihen mit jeweils eigenem Strom von Samples. In OpenTelemetry übernehmen Resource-Attribute wie service.name zusammen mit den Attributen der Metrik diese Rolle. Jeder Datenpunkt trägt zusätzlich eine Aggregationstemporalität, kumulativ oder Delta.
Warum die Kardinalität entscheidend ist
Die Anzahl unterschiedlicher Zeitreihen heißt Kardinalität. Sie wächst multiplikativ: Eine Metrik mit 20 Services, 3 Regionen, 10 Endpunkten und 5 Statuscodes kann bis zu 20 × 3 × 10 × 5 = 3.000 Zeitreihen erzeugen. Ein zusätzliches Label wie user_id mit 100.000 Werten macht daraus womöglich Hunderte Millionen. Jede aktive Zeitreihe kostet Speicher für den Index und Platz für ihre Samples. Hohe Kardinalität ist daher der häufigste Grund, warum Metriksysteme langsam oder teuer werden. Kennungen mit unbegrenzten Werten wie User-IDs, Request-IDs oder Trace-IDs gehören in Logs und Traces, nicht in Metrik-Labels.
Wie Zeitreihen gespeichert werden
Zeitreihendatenbanken (TSDBs) sind für einen Workload optimiert, der vor allem anhängt und nach Zeitbereichen liest. Die Samples einer Zeitreihe treffen in zeitlicher Reihenfolge ein und werden meist als Bereich abgefragt. TSDBs fassen sie deshalb in Chunks zusammen und komprimieren sie stark, etwa mit Delta-of-Delta-Kodierung für Zeitstempel und XOR-Kodierung für Gleitkommawerte, wie im Gorilla-Paper von Facebook beschrieben. Ältere Daten werden häufig per Downsampling verdichtet, zum Beispiel auf Fünf-Minuten-Mittelwerte, Minima und Maxima statt aller Rohwerte, und schließlich gemäß der Datenaufbewahrung gelöscht.
Zeitreihen abfragen
Abfragen wählen Zeitreihen über Name und Labels aus und aggregieren sie dann über die Zeit und über Dimensionen hinweg. Ein typisches PromQL-Beispiel berechnet den Fehleranteil pro Service über die letzten fünf Minuten:
sum by (service) (rate(http_server_requests_total{status=~"5.."}[5m]))
/
sum by (service) (rate(http_server_requests_total[5m]))
Dabei passieren zwei Schritte: rate() wandelt jede kumulative Zähler-Zeitreihe in eine Rate pro Sekunde um, und sum by (service) fasst alle Regionen, Endpunkte und Statuscodes zu einer Zeitreihe pro Service zusammen.
Best Practices
- Labels mit kleinem, begrenztem Wertebereich wählen und die Benennung über alle Services einheitlich halten.
- Counter und Histogramme statt vorberechneter Mittelwerte verwenden, da sie sich über Zeitreihen korrekt aggregieren lassen.
- Ein Scrape- oder Export-Intervall wählen, das zum Signal passt, typischerweise 10 bis 60 Sekunden.
- Die Zahl aktiver Zeitreihen pro Metrik überwachen, um Kardinalitätswachstum früh zu erkennen.
- Ungenutzte Zeitreihen beim Ingest verwerfen oder aggregieren, statt für ihre Speicherung zu zahlen.
Counter, Gauges und Histogramme
Was ein Sample-Wert bedeutet, hängt vom Metriktyp hinter der Zeitreihe ab:
- Counter steigen nur an, etwa die Gesamtzahl der Anfragen oder gesendeten Bytes. Abgefragt wird fast immer ihre Änderungsrate, nicht der Rohwert. Backends berücksichtigen dabei Zähler-Resets nach Neustarts.
- Gauges steigen und fallen und bilden einen aktuellen Zustand ab, etwa belegten Arbeitsspeicher, Queue-Länge oder Temperatur.
- Histogramme zählen Beobachtungen in Buckets, zum Beispiel Antwortzeiten. Ein klassisches Prometheus-Histogramm wird als eine Zeitreihe pro Bucket plus je eine Zeitreihe für Summe und Anzahl gespeichert. Deshalb erzeugen Histogramme schnell viele Zeitreihen.
Der Typ ist für korrekte Aggregation entscheidend: Gauges über Instanzen zu summieren ist meist unproblematisch, vorberechnete Perzentile zu mitteln dagegen nicht. Prüfen Sie deshalb vor jeder Abfrage, welcher Typ hinter einer Zeitreihe steckt.
Wie Obseria unterstützt
Obseria nimmt Metriken über OpenTelemetry und Prometheus an und macht sie per PromQL, OQL oder SQL abfragbar. Metrik-Datenpunkte werden 13 Monate aufbewahrt, was Vergleiche mit dem Vorjahr ermöglicht. Obseria Pipeline kann Labels beim Ingest filtern, aggregieren oder entfernen, um die Kardinalität im Griff zu behalten, und gefilterte Daten kosten nur die Ingestion. Die integrierte Anomalieerkennung lernt das normale Muster jeder Zeitreihe und hebt Abweichungen hervor.