Logs erfassen Ereignisse. Metriken messen Zustände. Traces verfolgen Anfragen durch verteilte Systeme. Diese drei Säulen der Observability haben sich in den letzten Jahren in fast jedem modernen IT-Betrieb etabliert. Doch eine vierte Säule gewinnt zunehmend an Bedeutung: das Continuous Profiling. Es beantwortet eine Frage, die Logs, Metriken und Traces häufig offenlassen: Warum genau ist dieser Code langsam?
Was Continuous Profiling ist – und was es nicht ist
Profiling selbst ist kein neues Konzept. Entwickler nutzen Profiler seit Jahrzehnten, um in Entwicklungsumgebungen Engpässe zu finden. Das Problem: Klassisches Profiling ist ein Ad-hoc-Werkzeug. Man aktiviert es manuell, läuft einen definierten Testlauf durch und wertet die Ergebnisse aus. In Produktionssystemen scheidet das in der Regel aus – zu hoch ist der Overhead, zu undefiniert das tatsächliche Nutzungsverhalten.
Continuous Profiling löst dieses Dilemma. Anstatt sporadisch und mit hohem Overhead zu profilen, werden Produktionssysteme mit extrem niedrigem Overhead kontinuierlich beobachtet. Die Daten werden dauerhaft gesammelt, aggregiert und über die Zeit hinweg auswertbar gespeichert. Das Ergebnis: Statt zu fragen „Was war langsam während meines gestrigen Lasttests?", kann man fragen „Welche Funktion verbrauchte gestern zwischen 14:00 und 14:30 Uhr am meisten CPU – genau während des Incidents?"
Wie eBPF das Profiling in der Produktion erst möglich macht
Der technologische Schlüssel hinter modernem Continuous Profiling ist eBPF (extended Berkeley Packet Filter). eBPF ist eine Kernel-Technologie, die es ermöglicht, kleine Programme direkt im Linux-Kernel auszuführen – ohne den Kernel-Quellcode zu verändern und ohne Kernel-Module zu laden.
Für das Profiling bedeutet das: eBPF-basierte Profiler können CPU-Nutzung, Memory-Allokationen und Systemaufrufe auf Kernel-Ebene messen, ohne dass die zu profilierende Anwendung irgendwie angepasst werden muss. Kein Code-Instrumentation, keine Agent-Libraries, kein Neustart der Applikation.
Konkrete Eigenschaften, die eBPF für Continuous Profiling attraktiv machen:
- Minimaler Overhead: Messungen auf eBPF-Basis verursachen typischerweise weniger als 1 % CPU-Overhead – akzeptabel für Produktionssysteme.
- Keine Instrumentation notwendig: Jede laufende Anwendung kann profiliert werden, unabhängig von Sprache oder Build-System.
- Sprachenübergreifend: eBPF-Profiler funktionieren mit Go, Java, Python, Rust, C++ und anderen Sprachen gleichzeitig.
- Kernel und User Space: Es können sowohl Kernel-Funktionen als auch Anwendungscode in einem gemeinsamen Profil dargestellt werden.
Pyroscope: Das Open-Source-Werkzeug für Continuous Profiling
Pyroscope ist ein Open-Source-Tool für Continuous Profiling, das von Grafana Labs übernommen und weiterentwickelt wurde. Es nutzt eBPF als Backend für sprachenübergreifendes Profiling und bietet eine integrierte Web-Oberfläche zur Visualisierung der gesammelten Daten.
Die Architektur von Pyroscope besteht aus zwei Kernkomponenten:
- Pyroscope Agent: Läuft auf jedem profilierten Host oder Pod und sammelt kontinuierlich Profiling-Daten mit eBPF oder sprachspezifischen Integrations-SDKs.
- Pyroscope Server: Empfängt die Profiling-Daten, aggregiert sie und stellt sie für Abfragen und Visualisierungen zur Verfügung.
Grafana Labs hat Pyroscope eng in das Grafana-Ökosystem integriert. Wer bereits Grafana, Prometheus und Loki nutzt, kann Profiling-Daten direkt in Grafana Dashboards neben Metriken und Logs einblenden – eine gemeinsame Zeitleiste, auf der Metrikanstieg und Code-Engpass zusammen sichtbar werden.
Flame Graphs: Das Herzstück der Profiling-Visualisierung
Das wichtigste Visualisierungsformat im Profiling ist der Flame Graph. Entwickelt von Brendan Gregg bei Netflix, stellt er Call-Stacks so dar, dass sofort erkennbar ist, welche Funktionen den meisten CPU-Anteil verbrauchen.
Wie ein Flame Graph zu lesen ist:
- Die X-Achse zeigt den relativen Zeitanteil (oder Stichprobenanteil), nicht den zeitlichen Verlauf.
- Die Y-Achse zeigt die Call-Stack-Tiefe: Unten die oberste Funktion, oben die innersten Aufrufe.
- Breite Blöcke bedeuten hohen CPU-Anteil. Schmale Blöcke sind vergleichsweise vernachlässigbar.
Mit Flame Graphs lassen sich in Minuten Muster identifizieren, die in klassischen Metriken unsichtbar bleiben. Eine Funktion, die 40 % der CPU-Zeit verbraucht, ist im Flame Graph sofort als breiter Block erkennbar – ohne dass man tausende Log-Zeilen durchsuchen müsste.
Konkrete Anwendungsfälle in der Praxis
Continuous Profiling ist kein akademisches Konzept. Es löst handfeste Probleme im täglichen IT-Betrieb:
Memory Leaks in Produktionssystemen finden
Memory Leaks manifestieren sich oft erst nach Stunden oder Tagen im Betrieb. Metriken zeigen den steigenden Speicherverbrauch, sagen aber nicht warum. Continuous Profiling macht sichtbar, welche Allokationen im Zeitverlauf zunehmen – und in welchem Code-Pfad sie entstehen.
Unerwartete CPU-Spitzen untersuchen
Ein Monitoring-Alert zeigt: CPU 90 % seit 5 Minuten. Ohne Profiling ist die Diagnose ein Ratespiel. Mit Continuous Profiling öffnet man den Flame Graph für genau diesen Zeitraum und sieht, welche Funktion den Anstieg verursacht hat.
Regressionen nach Deployments erkennen
Continuous Profiling erlaubt direkten Vergleich: Wie sah das CPU-Profil vor dem Deployment aus? Wie danach? Flamegraph-Differenzansichten (Diff Flame Graphs) machen Regressionen auf Funktionsebene sofort sichtbar.
Integration in den bestehenden Observability-Stack
Continuous Profiling entfaltet seinen vollen Wert als Teil eines zusammenhängenden Observability-Stacks – nicht als isoliertes Werkzeug. Die ideale Integration sieht so aus:
- Metriken (Prometheus): Zeigen wann ein Problem aufgetreten ist.
- Logs (Loki): Zeigen welche Ereignisse zeitgleich stattfanden.
- Traces (Tempo): Zeigen welcher Request-Pfad betroffen war.
- Profiles (Pyroscope): Zeigen warum der Code in diesem Moment langsam war.
In Grafana lassen sich alle vier Datenquellen gemeinsam in einem Dashboard darstellen und über Zeitkorrelationen verknüpfen. Aus einem Latenzanstieg im Trace springt man per Klick in das Profil des betroffenen Services – und sieht in Sekunden, welche Funktion verantwortlich ist.
Einstieg ohne großen Aufwand
Der praktische Einstieg in Continuous Profiling erfordert keine umfangreiche Neuarchitektur. Wer bereits Kubernetes nutzt, kann den Pyroscope-Agenten als DaemonSet deployen und beginnt innerhalb von Minuten, Profiling-Daten zu sammeln. Bestehende Grafana-Instanzen lassen sich mit dem Pyroscope-Datasource-Plugin erweitern.
Für Teams ohne Kubernetes-Umgebung bietet Pyroscope auch klassische Linux-Agents und Docker-basierte Setups. Der Overhead ist so gering, dass ein produktiver Einsatz auf allen relevanten Hosts ohne Bedenken möglich ist.
Continuous Profiling schließt eine Lücke, die Logs, Metriken und Traces allein nicht füllen können. Es macht Systeme tiefer verstehbar – und gibt Teams die Werkzeuge, um Performance-Probleme nicht nur zu erkennen, sondern wirklich zu erklären.
Bildquelle: Pexels, Foto von Brett Sayles (pexels.com/photo/1148820) – Lizenz: Pexels License (kostenlos nutzbar)
Quellen:
Brendan Gregg: Flame Graphs – brendangregg.com/flamegraphs.html
Grafana Labs: Pyroscope Dokumentation – grafana.com/docs/pyroscope
Linux Foundation: eBPF Dokumentation – ebpf.io