zurück zum Artikel

Prometheus-Monitoring für Java-Entwickler

Werkzeuge
Prometheus-Monitoring für Java-Entwickler

Anders als traditionelle Monitoring-Tools wie Nagios verfolgt Prometheus einen White-Box-Ansatz: Es wird nicht nur geprüft, ob eine Applikation läuft, sondern Applikationen stellen aktiv Metriken über ihren internen Status bereit.

Dieser Artikel wendet sich an Java-Entwickler, die bisher keine Erfahrung mit Prometheus haben. Der erste Teil des Artikels gibt eine allgemeine Einführung in Prometheus, der zweite Teil beschreibt, wie man Java-Programme instrumentiert, um Metriken für das Monitoring mit Prometheus bereitzustellen.

Modulare Architektur

Einer der Erfolgsfaktoren von Prometheus, das konzeptionell auf Googles internem Borgmon-System beruht, ist der modulare Aufbau. Das zentrale Modul ist der Prometheus-Server, der eine Time-Series-Datenbank und die zugehörige Abfragesprache PromQL bereitstellt. Die Datenbank speichert Folgen von 64-Bit-Fließkommazahlen zusammen mit dem jeweiligen Zeitstempel, der anzeigt, wann der Wert in die Datenbank aufgenommen wurde. Mit PromQL lassen sich die Zeitreihen statistisch auswerten und miteinander in Relation bringen.

Weitere Funktionen, die man von einer vollständigen Monitoring-Software erwartet, steuern externe Tools bei. Die drei wichtigsten Komponenten sind:

Der modulare Ansatz führt dazu, dass jedes Modul einen klaren Fokus und überschaubaren Umfang hat. Das Modell passt gut zur Open-Source-Philosophie von Prometheus: Rund um den Prometheus-Server hat sich ein umfangreiches Ökosystem aus vielen kleinen und größeren Projekten gebildet, die jeweils spezifische Aufgaben übernehmen.

Getting Started

Das folgende Set-up genügt, um die Beispiele zu PromQL im nachfolgenden Abschnitt praktisch am eigenen PC auszuprobieren. Ein etwas ausführlicheres Tutorial ist als 30-minütiges Video verfügbar [2].

Schritt 1: Metriken bereitstellen

Um sich mit Prometheus vertraut zu machen, benötigt man als erstes Metriken. Eine einfache Möglichkeit zur Bereitstellung bietet der node_exporter [3]. Das ist ein Programm, das Betriebssystemmetriken wie Netzwerk, Festplatte oder CPU liefert. Der Download von der GitHub-Release-Seite umfasst den Exporter als ausführbare Datei, die sich in der Default-Konfiguration ohne weitere Parameter starten lässt. Nach dem Start stehen die Metriken unter http://localhost:9100/metrics bereit. Der Webbrowser zeigt unter dieser URL eine für Menschen lesbare Darstellung der Metriken.

Schritt 2: Metriken in den Prometheus-Server einlesen

In Schritt zwei sollen die Metriken in die Time-Series-Datenbank des Prometheus-Servers eingelesen werden. Dazu laden Entwickler zunächst den Prometheus-Server von der GitHub-Release-Seite herunter, entpacken den Download und bearbeiten die Beispielkonfigurationsdatei prometheus.yml. Um die Metriken aus dem node_exporter abzufragen, fügt man am Ende der Datei im Abschnitt scrape_configs folgende Job-Definition hinzu:

- job_name: 'node'
static_configs:
- targets: ['localhost:9100']

Der Prometheus-Server wird mit folgendem Befehl gestartet:

./prometheus -config.file ./prometheus.yml

Nach erfolgreichem Start stellt der Prometheus-Server ein Web-Interface zum Debugging unter http://localhost:9090 bereit. Unter Status | Targets sieht man, dass das Target auf Port 9100 "up" ist.

PromQL, Grafana

Die Prometheus Query Language

PromQL ist die Abfragesprache, mit der sich die Daten aus der Time-Series-Datenbank auswerten lassen. In der Prometheus-Debugging-UI unter http://localhost:9090 kann man im Tab "Graph" PromQL-Abfragen testen und die Ergebnisse einsehen.

Die einfachste Query ist der Name einer Metrik, zum Beispiel:

node_network_receive_bytes

Es zeigt sich, dass sich hinter einem Metrikmamen mehrere Zeitreihen verbergen können, die jeweils mit verschiedenen Labels gekennzeichnet sind. Zum Beispiel liefert node_network_receive_bytes eine Metrik für das Netzwerk-Device eth0 und eine Metrik für das Device lo. Ein Filter schränkt die Anzeige der Metriken weiter ein:

node_network_receive_bytes{device='eth0'}

Die Abfrage liefert jeweils den neuesten verfügbaren Wert in der Zeitreihe. Ist man nicht nur an diesem Wert interessiert, sondern am Zeitverlauf, dann lässt sich der Query ein Zeitintervall in eckigen Klammern hinzufügen. Nachfolgende Abfrage zeigt alle Werte der letzten fünf Minuten zusammen mit den jeweiligen Zeitstempeln, die anzeigen, wann die Werte eingelesen wurden:

node_network_receive_bytes{device='eth0'}[5m]

Neben den bisher gezeigten grundlegenden Funktionen bietet PromQL weitere, mit denen unter anderem statistische Auswertungen möglich sind. Ein Beispiel hierfür ist die rate()-Funktion, die einen Zeitverlauf als Parameter nimmt und den Durchschnittswert pro Sekunde liefert:

rate(node_network_receive_bytes{device='eth0'}[5m])

Die Query zeigt, wie viele Bytes pro Sekunde über das Netzwerk-Device eth0 in den letzten fünf Minuten im Durchschnitt empfangen wurden.

PromQL kann auch mehrere Metriken kombinieren. Um beispielsweise nicht nur die empfangenen Bytes zu sehen, sondern den gesamten I/O-Traffic am Device eth0, erweitert man den Beispielaufruf folgendermaßen:

rate(node_network_transmit_bytes{device='eth0'}[5m]) + 
rate(node_network_receive_bytes{device='eth0'}[5m])

Diese Beispiele zeigen nur einen kleinen Ausschnitt der Möglichkeiten von PromQL. Die PromQL-Dokumentation beschreibt eine Vielzahl weiterer Funktionen [4] der Abfragesprache.

Dashboard für den echten Monitoring-Betrieb

Die eingebaute Weboberfläche in Prometheus ist hauptsächlich zum Debugging gedacht und bietet eine schnelle und einfache Möglichkeit, Queries auszuprobieren. Für den echten Monitoring-Betrieb kommt meist Grafana [5] als Dashboard zum Einsatz. Die Erweiterung stellt das Ergebnis beliebiger PromQL-Queries grafisch dar. Grafana ist wie Prometheus eineausführbare Datei. Nach dem Start stellt es eine Weboberfläche unter http://localhost:3000 bereit. Das Tool wird vollständig über die Weboberfläche konfiguriert, sodass kein Editieren von Konfigurationsdateien nötig ist.

Beim Erstellen eines Dashboards wählt man aus verschiedenen Visualisierungskomponenten beispielsweise Liniendiagramme und konfiguriert anschließend die PromQL-Query, deren Ergebnis am Ende mit dem jeweiligen Diagrammtyp visualisiert werden soll.

Beispielhafter Grafana-Screenshot
Beispielhafter Grafana-Screenshot (Bild: http://grafana.org/assets/img/features/dashboard_ex.png)

Auf ein Grafana-Beispiel verzichtet dieser Artikel, doch es sei darauf hingewiesen, dass die von Grafana visualisierten Daten Ergebnisse von PromQL-Queries sind. Es werden also in Grafana dieselben Queries hinterlegt, die sich in der Prometheus-Debugging-Oberfläche ausprobieren lassen. Die Erweiterung sendet demnach die Queries an Prometheus und stellt die Ergebnisse grafisch dar.

Java

Instrumentieren von Java-Anwendungen

Bisher stellte der Artikel Prometheus allgemein vor und beschrieb anhand von Beispielen, wie sich die Software aufsetzen lässt und die ersten Queries durchgeführt werden. Für den effizienten Einsatz von Prometheus für Java-Serveranwendungen reicht es jedoch nicht, mit bestehenden Exportern Betriebssysteme zu überwachen. Ziel ist es daher, dass Java-Anwendungen aktiv Metriken über ihren internen Zustand bereitstellen.

Alle Metriken laufen im Prometheus-Server zusammen und können mithilfe von PromQL ausgewertet und miteinander in Relation gebracht werden. Beispiele für typische Metriken von Java-Applikationen sind Anzahl und Dauer von Aufrufen pro REST-URL oder die Anzahl von Business-Transaktionen.

Für die Instrumentierung von Java-Anwendung mit Prometheus-Metriken gibt es grundsätzlich zwei Möglichkeiten:

  1. Die direkte Instrumentierung mit der Prometheus Client Library für Java [6] ist die einfachste Art, Java-Code für Prometheus zu instrumentieren.
  2. Mapping von 3rd-Party-Metriken nach Prometheus: Falls es nicht möglich ist, die Prometheus-Client-Bibliothek direkt zu nutzen – beispielsweise wenn das Projekt einen anderen Mechanismus zur Instrumentierung nutzt oder sich der Quelltext nicht ändern lässt – steht eine Vielzahl von Bibliotheken bereit, um 3rd-Party-Metriken für Prometheus aufzubereiten.

In den folgenden Abschnitten werden die beiden Möglichkeiten zur Instrumentierung von Java-Anwendungen vorgestellt.

Direkte Instrumentierung

Die Java-Bibliothek zur Instrumentierung für Prometheus lässt sich als einfache Maven-Dependency einbinden:

<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_common</artifactId>
<version>0.0.16</version>
</dependency>

Die Metriken werden im Code einfach über statische Builder-Methoden erzeugt. Hier ein Beispiel für eine Counter-Metrik:

private final Counter counter = Counter.build()
.name("requests_total")
.help("Total number of requests.")
.register();

Die Java-Client-Bibliothek stellt vier Arten von Metriken zur Verfügung, die sich im Java-Code verwenden lassen:

Die Prometheus-Client-Bibliothek stellt eine Prometheus-Registry bereit, die als Singleton implementiert ist und Referenzen auf alle Metriken verwaltet. Im Code-Beispiel oben wird mit dem Aufruf von register() die Counter-Metrik in der Registry registriert.

Um die Metriken aus der Prometheus-Registry über einen HTTP-Aufruf verfügbar zu machen, kann man mit der Methode TextFormat.write004() den Inhalt aller Metriken in einen Output-Stream serialisieren:

TextFormat.write004(responseWriter, CollectorRegistry.
defaultRegistry.metricFamilySamples());

Der responseWriter gehört zur HTTP-Response, die an den Prometheus-Server übertragen wird. Das HTTP-Response-Objekt wird je nach eingesetztem Framework (Servlet, JAX-RS etc.) auf unterschiedliche Arten bereitgestellt.

Instrumentierung mit 3rd-Party-Metriken

Viele Applikationen verwenden bereits Tools, um Metriken bereitzustellen. In dem Fall ist es nicht nötig, die Prometheus-Client-Bibliothek parallel zu den bestehenden Tools einzubauen. Vielmehr ist es in den meisten Fällen möglich, die Metriken für Prometheus verfügbar zu machen. Hierfür stehen im GitHub Repository der Prometheus Client Library für Java [8] entsprechende Implementierungen zur Verfügung.

Spring Boot Actuators

Spring Boot bringt das Actuator-Framework mit, um Anwendungen zu instrumentieren und Metriken bereitzustellen. Die Java-Client-Bibliothek für Prometheus implementiert eine Klasse SpringBootMetricsCollector, die Actuator-Metriken in Prometheus-Metriken konvertiert. Über die Annotation @EnablePrometheusEndpoint werden dann die Prometheus-Metriken bereitgestellt.

JMX

Wer Java-EE-konforme Serverapplikationen schreibt, kommt um den JMX-Standard (Java Management Extensions) nicht herum. Um Metriken über eine bestehende JMX-Applikation für Prometheus zur Verfügung zu stellen, kann man den jmx_exporter [9] verwenden. Das ist ein externes Programm, das die JMX Beans ausliest, die entsprechenden Daten in Prometheus-Metriken konvertiert und dann bereitstellt. Der jmx_exporter wird entweder als eigenständige Applikation betrieben, die auf die JMX Beans zugreift, oder als Agent innerhalb der bestehenden JVM. In beiden Fällen braucht der Quellcode der Java-Applikation nicht geändert zu werden.

Das Prometheus-Monitoring von JMX-Applikationen hat gewisse Grenzen. Beispielsweise sind die Datenmodelle von JMX und Prometheus nicht 100 Prozent kompatibel: JMX ermöglicht es, beliebige Daten bereitzustellen, während Prometheus nur Fließkommazahlen verarbeitet. Es lassen sich also nicht alle JMX-Informationen in Prometheus übernehmen. Außerdem kann das Auslesen aller JMX Beans zeitaufwendig sein, insbesondere wenn die JMX Beans ihrerseits Metriken "on the fly" akquirieren. Deshalb sollte beim Einsatz des jmx_exporter mithilfe von Black- oder Whitelists festgelegt werden, welche Beans geladen werden. Berücksichtigt man diese Einschränkungen, ist der jmx_exporter eine gute Möglichkeit, Legacy-Java-Applikationen in Prometheus-Monitoring-Infrastrukturen einzubinden.

Weitere Frameworks

Neben den großen Frameworks Spring und Java EE gibt es noch eine Vielzahl kleinerer Frameworks, die ebenfalls Instrumentierung anbieten. Einige davon werden von der Prometheus Client Library für Java [10] unterstützt. Als Beispiel sei hier die Dropwizard Metrics Library [11] genannt. Die Client-Bibliothek bietet hierfür die Klasse DropwizardExports, die Dropwizard-Metriken für Prometheus exportiert. Auch für weitere Libraries stehen in den Java Client Bridges zur Verfügung, es lohnt sich daher einen Blick in die Subprojekte zu werfen.

Fazit

Prometheus ist eine modular aufgebaute Monitoring-Software, die auf einer Time-Series-Datenbank basiert. Die einzelnen Komponenten sind einfach zu installieren und zu betreiben. Die Metriken laufen im Prometheus-Server zusammen, wo sie sich mithilfe der Abfragesprache PromQL auswerten lassen.

Um die Vorteile von Prometheus effizient zu nutzen, sollten Applikationen Metriken über ihren internen Zustand aktiv bereitstellen, sodass sich diese im Prometheus-Server auswerten und mit anderen Metriken korrelieren lassen. Für Java-Applikationen steht eine Vielzahl fertiger Optionen zur Instrumentierung zur Verfügung, je nachdem, ob die Java-Applikation direkt für Prometheus instrumentiert oder 3rd-Party-Metriken für Prometheus verfügbar gemacht werden sollen.

Aufgrund der geringen Einstiegshürde ist es möglich, mit wenig Aufwand einen Prometheus-Server aufzusetzen und einige Metriken bereitzustellen, um mit dem System Erfahrungen zu sammeln. (ane [12])

Dr. Fabian Stäber
ist Softwareentwickler, R&D-Leiter, Consultant und Architekt bei der ConSol Software GmbH in München. Er ist Autor des Grok Exporter [13], eines Tools zum Logfile-Monitoring mit Prometheus.


URL dieses Artikels:
http://www.heise.de/-3589523

Links in diesem Artikel:
[1] https://prometheus.io/docs/instrumenting/exporters/
[2] https://labs.consol.de/monitoring/2016/11/10/devoxx.html
[3] https://github.com/prometheus/node_exporter
[4] https://prometheus.io/docs/querying/functions/
[5] http://grafana.org/
[6] https://github.com/prometheus/client_java
[7] https://prometheus.io/docs/practices/histograms/
[8] https://github.com/prometheus/client_java
[9] https://github.com/prometheus/jmx_exporter
[10] https://github.com/prometheus/client_java
[11] http://metrics.dropwizard.io/3.1.0/
[12] mailto:ane@heise.de
[13] https://github.com/fstab/grok_exporter