Lexikon · H

Histogramm

Ein Metriktyp, der Messwerte in Buckets zählt, sodass sich Perzentile wie p95 oder p99 berechnen und über Instanzen aggregieren lassen.

Von Obseria-RedaktionAktualisiert

Definition

Ein Histogramm ist ein Metriktyp, der die Verteilung von Messwerten wie Request-Dauern erfasst, indem er Beobachtungen in Buckets zählt und zusätzlich Summe und Anzahl speichert. Anders als ein Mittelwert erlaubt ein Histogramm, Perzentile wie p95 oder p99 zu schätzen und Verteilungen korrekt über viele Instanzen und Zeitfenster zu aggregieren.

Was ist ein Histogramm?

Ein Histogramm ist in der Observability ein Metrik-Typ, der festhält, wie sich Werte verteilen, und nicht nur ihren Durchschnitt. Jedes Mal, wenn ein Request endet, wird seine Dauer „beobachtet“: Das Histogramm erhöht den Zähler des passenden Buckets, addiert den Wert zu einer laufenden Summe und erhöht die Gesamtzahl. Aus diesen Zählern lassen sich später Fragen beantworten wie „Wie viele Requests dauerten länger als 300 ms?“ oder „Wie hoch war die p99-Latenz der letzten fünf Minuten?“.

Histogramme sind der Standard, um Latenzen, Payload-Größen, Wartezeiten in Queues und ähnliche Werte zu messen, bei denen das Tail wichtiger ist als der Mittelwert. Weil Bucket-Zähler einfache Zahlen sind, lassen sich Histogramme von Hunderten Pods addieren und ergeben trotzdem eine gültige Verteilung. Für vorab berechnete Perzentile gilt das nicht.

Klassische Prometheus-Histogramme und le-Buckets

Ein klassisches Prometheus-Histogramm namens http_request_duration_seconds liefert drei Arten von Zeitreihen:

  • http_request_duration_seconds_bucket{le="0.25"}: kumulative Zähler, einer pro Obergrenze (le steht für „less than or equal“), immer inklusive le="+Inf".
  • http_request_duration_seconds_sum: die Summe aller beobachteten Werte.
  • http_request_duration_seconds_count: die Anzahl der Beobachtungen, identisch mit dem +Inf-Bucket.

Die Bucket-Grenzen werden bei der Instrumentierung festgelegt. Viele Prometheus-Client-Bibliotheken nutzen standardmäßig 5 ms bis 10 s (.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10). Jeder Bucket ist pro Label-Kombination eine eigene Zeitreihe. Zehn Buckets mal viele Labels treiben die Kardinalität daher schnell nach oben.

Perzentile mit histogram_quantile berechnen

In PromQL schätzen Sie ein Perzentil aus den Bucket-Raten:

histogram_quantile(0.99,
  sum by (le, service) (rate(http_request_duration_seconds_bucket[5m])))

Die Funktion sucht den Bucket, der den gesuchten Rang enthält, und interpoliert darin linear. Das Ergebnis ist eine Schätzung, deren Genauigkeit vom Bucket-Layout abhängt: Liegen die Grenzen bei 250 ms und 500 ms, bedeutet ein ausgewiesenes p99 von 400 ms nur „irgendwo zwischen 250 und 500 ms“. Aggregieren Sie immer zuerst mit sum by (le) und behalten Sie das Label le in der Gruppierung.

Exponentielle und native Histogramme

Feste Buckets erzwingen einen Kompromiss zwischen Genauigkeit und Kosten. Zwei neuere Formate lösen das mit exponentiell wachsenden Buckets, die keine manuelle Konfiguration brauchen:

FormatBucketsHinweise
Klassisches Prometheus-HistogrammFeste, selbst definierte le-GrenzenEine Zeitreihe pro Bucket, breit unterstützt
OpenTelemetry Explicit Bucket HistogramFeste Grenzen pro Instrument oder ViewEntspricht dem klassischen Histogramm
OpenTelemetry Exponential HistogramBasis 2^(2^-scale), Scale passt sich automatisch anBegrenzte Bucket-Anzahl, konstanter relativer Fehler
Prometheus Native HistogramExponentielles Schema, sparse BucketsGanzes Histogramm in einer Zeitreihe; stabil seit Prometheus 3.8, Scraping per Opt-in

Mit exponentiellen Buckets ist der relative Fehler bei 2 ms genauso groß wie bei 20 s, und das SDK senkt die Scale, wenn die Werte zu weit streuen. Native Histograms und OTel-Exponential-Histogramme sind ineinander überführbar und reduzieren die Zahl der Zeitreihen gegenüber klassischen Buckets erheblich.

Rechenbeispiel: ein Histogramm lesen

Ein illustratives Zeitfenster für einen Service zeigt folgende Bucket-Raten pro Sekunde: le="0.1" 900, le="0.25" 970, le="0.5" 995 und le="+Inf" 1000. Demnach waren 90 Prozent der Requests nach 100 ms fertig, 97 Prozent nach 250 ms und 99,5 Prozent nach 500 ms. Der p99-Rang (990) liegt im Bucket zwischen 250 und 500 ms, der 25 Requests pro Sekunde enthält; die lineare Interpolation landet bei etwa 450 ms. Die 5 Requests pro Sekunde oberhalb von 500 ms werden zwar gezählt, ihre genaue Dauer bleibt aber unbekannt. Deshalb sollte der höchste endliche Bucket oberhalb jedes Werts liegen, der für Sie relevant ist, etwa oberhalb Ihres Timeouts.

Histogramm oder Summary?

Prometheus kennt zusätzlich den Typ Summary, der Quantile direkt im Client berechnet. Für eine einzelne Instanz sind Summaries präzise, ihre Quantile lassen sich aber nicht über Instanzen mitteln oder addieren. Für Services mit mehr als einer Replica ist das Histogramm daher fast immer die bessere Wahl. Histogramme können außerdem Exemplars tragen, also Trace-IDs an einzelnen Buckets, die einen langsamen Bucket direkt mit einem repräsentativen Trace verknüpfen.

Best Practices und typische Fehler

  • Bucket-Grenzen auf SLO-Schwellen legen. Lautet das Ziel „99 Prozent unter 300 ms“, liefert ein Bucket le="0.3" ein exaktes Verhältnis statt einer interpolierten Schätzung.
  • Exponentielle oder native Histogramme bevorzugen, wo Ihr Stack sie unterstützt, damit Sie kein Bucket-Layout raten müssen.
  • Keine Perzentile mitteln. Erst Bucket-Zähler aggregieren, dann das Quantil berechnen.
  • Label-Kardinalität im Blick behalten. Ein Histogramm mit User-IDs als Label vervielfacht jeden Bucket.
  • Summe und Anzahl mitnutzen: rate(_sum) / rate(_count) ergibt den Mittelwert, eine sinnvolle Ergänzung zum Tail.

Wie Obseria hilft

Obseria nimmt OpenTelemetry-Histogramme über OTLP entgegen, auch exponentielle, und unterstützt neben OQL und SQL auch PromQL, sodass bestehende histogram_quantile-Abfragen weiter funktionieren. Metrik-Datenpunkte werden 13 Monate aufbewahrt, was langfristige Latenzverteilungen und SLO-Reporting ermöglicht. Über Exemplars gelangen Sie von einem Bucket direkt zum passenden Trace im Distributed Tracing.

Häufig gestellte Fragen

le steht für „less than or equal“. Jede _bucket-Zeitreihe zählt alle Beobachtungen bis zu dieser Obergrenze. Die Buckets sind also kumulativ, und der Bucket le="+Inf" entspricht der Gesamtzahl.

Die Funktion interpoliert linear innerhalb des Buckets, der den gesuchten Rang enthält. Die Genauigkeit hängt deshalb von der Bucket-Breite ab. Schmale Buckets um wichtige Schwellen oder exponentielle bzw. native Histogramme liefern deutlich bessere Schätzungen.

Ein OpenTelemetry-Histogramm, dessen Bucket-Grenzen um einen konstanten Faktor wachsen, den ein Scale-Parameter bestimmt. Das SDK passt die Scale automatisch an, damit die Daten in eine begrenzte Anzahl von Buckets passen. Eine manuelle Bucket-Konfiguration entfällt.

Nutzen Sie ein Histogramm, sobald mehrere Instanzen laufen oder aggregiert werden soll, denn Bucket-Zähler lassen sich addieren. Summaries berechnen Quantile pro Instanz und lassen sich nicht sinnvoll zusammenführen.

Setzen Sie das Wissen in die Praxis um

Testen Sie Obseria 14 Tage kostenlos, mit OpenTelemetry und ohne proprietäre Agenten.