Anwendungsmonitoring mit Prometheus

02.09.2024
Development Monitoring Django

Es existieren zahlreiche Tools, die Überwachen, ob eine Webanwendung noch online ist. Über den weiteren Zustand der Anwendung können jedoch in der Regel keine Aussagen getroffen werden. Die Hoffnung besteht, dass die User die Fehler melden, die sie entdecken, allerdings wird das auf lange Sicht Frust erzeugen. Bei öffentlichen Anwendungen und Diensten könnte dieser Ansatz sogar dazu führen, dass die Benutzer die Anwendung nicht weiter nutzen, ohne zu Kommunizieren, was das Problem war. Wird also ein grober Fehler in eine öffentliche Webanwendung ausgerollt, könnte sich das nach einiger Zeit bei den monatlichen Besuchen bemerkbar machen. Dann ist der Schaden allerdings schon angerichtet.

Django Fehlermeldungen

Eine bessere Herangehensweise ist daher die proaktive Überwachung der Anwendung. Eine standardmäßig unterstützte Funktion ist dabei, dass Personen in der ADMINS Variable in settings.py bei einem Internal Server Error eine Email erhalten, falls das Senden von Emails konfiguriert ist.

ADMINS ist dabei eine Liste aus Tupeln aus einem Namen und einer Emailadresse. Also beispielsweise:

ADMINS = [("Olaf", "olaf@deinefirma.de"), ("Anna", "anna@dienstleister.de")]

Dabei ist zu beachten, dass bei jedem Fehler eine Email geschickt wird, zum Beispiel auch wenn die Webanwendung über eine Url aufgerufen wird, die nicht in den ALLOWED_HOSTS freigegeben ist. Auf großen Seiten kann das zu sehr vielen Emails führen, was in der Regel bedeutet, dass die Emailbenachrichtungen ignoriert werden.

Prometheus

Eine andere Herangehensweise ist das Exponieren von Metriken in der Anwendung, die anschließend mit Tools wie Prometheus und Grafana gesammelt und ausgewertet werden können. Es ist üblich, dass die Anwendung dazu die Metriken in einem bestimmten Format unter einem Pfad bereitstellt und Prometheus so konfiguriert wird, dass die Metriken in vordefinierten Intervallen abgefragt werden. Dabei sind je nach Anwendungsfall 15s üblich und möglich. Prometheus wird dann in Grafana als Datenquelle hinterlegt und füllt so die Dashboards.

Für Django gibt es mit django-prometheus eine Bibliothek, die eine bestehende Django Anwendung um vordefinierte Metriken erweitert, die direkt von Prometheus eingesammelt werden können.

Problemtaisch wird die Verwendung dieser Bibliothek allerdings beim produktiven Hosten der Django Anwendung. Üblicherweise werden Django Anwendungen mit WSGI Anwendungsservern wie gunicorn betrieben, die mittels der Flag -w mehrere Replicas der Anwendung in mehreren Arbeiterprotessen starten, um eine horizontale Skalierung der Anwendung zu erreichen:

gunicorn --bind=0.0.0.0 -w 4 myapplication.wsgi

Jedoch würde in diesem Fall jeder Arbeiterprozess ein eigenes Set an Metriken erstellen. Prometheus würde zufällig die Metriken der einzelnen Arbeitsprozesse nacheinander einlesen und falsch auswerten, denn die Metriken müssen in diesem Fall summiert werden. Dieses Problem tritt ebenfalls auf wenn die Anwendung in Kubernetes horizontal skaliert wird.

Eine vorgesehene Lösung ist jedem Arbeitsprozess zu ermöglichen sich an einen eigenen Port des Servers zu binden und alle Prozesse und ihre Ports einzeln in Prometheus zu hinterlegen. In der Auswertung muss dann über die Arbeiter-Instanz summiert werden, um korrekte Metriken zu erhalten.

In Django setzen wir daher die PROMETHEUS_METRICS_EXPORT_PORT_RANGE Variable auf eine range die für jeden Arbeitsprozess einen Port liefert:

PROMETHEUS_METRICS_EXPORT_PORT_RANGE = range(8000, 8004)

Da wir schon dabei sind macht es Sinn den Metriken unserer Anwendung ein Prefix zu geben, sodass wir sie später von den Metriken anderer Django Anwendungen unterscheiden können:

PROMETHEUS_METRIC_NAMESPACE = "myapplication"

In der prometheus.yml hinterlegen wir anschließend die einzelnen Arbeitsprozesse mit ihren Ports:

scrape_configs:
  - job_name: "myapplication"
    static_configs:
      - targets:
          [
            "my.application.com:8000",
            "my.application.com:8001",
            "my.application.com:8002",
            "my.application.com:8003",
          ]
    metrics_path: "/metrics"

In Prometheus können wir anschließend die Metriken mit einer sum without über die instance so summieren wie wir es benötigen. Hier ein Beispiel für die Rate der HTTP Responses nach Status Code pro Minute:

sum without(instance) (rate(myapplication_django_http_responses_total_by_status_total[1m]))

Schlussendlich können wir Grafana nutzen, um diese Daten zu visualisieren. Da Prometheus auf das Speichern und Auswerten von Time Series Daten spezialisiert bleiben diese Visualisierungen auch bei mehreren unterschiedlichen Grafen stets performant. Eine Auswertung wie die obige über einen Zeitraum von fünf Tagen mit einer Auflösung von 15 Sekunden dauert nur einige Hundert Millisekunden.

Neugierig geworden? Falls Sie solch ein Monitoring auch für Ihre Anwendungen wünschen, kontaktieren Sie uns gerne.

Impressum

Screenion GmbH

Büroanschrift:
Adenauerallee 21, 1. OG
61440 Oberursel

Rechnungsanschrift und Firmensitz:
Oberhöchstadter Straße 70a
61440 Oberursel
Deutschland

Fon: +49 (0)6171 9519800
Fax: 06171-9519808
post@screenion.de
Web: https://www.screenion.de

Geschäftsführer: Reto M. Kiefer
Amtsgericht: Bad Homburg HRB 13769
UmSt-Id gemäß §27a Umsatzsteuergesetz: DE273300425

Datenschutz

Mit Ihrem Zugriff auf unsere Website werden Daten, die eine Identifizierung ermöglichen könnten (z.B. IP-Adresse) und weitere Angaben wie Datum, Uhrzeit und aufgerufene Seite In Log-Files gespeichert.

Eine Auswertung der Daten, außer für statistische Zwecke sowie zur Optimierung unseres Internetangebots in anonymisierter Form, findet nicht statt. Sie können unsere Website grundsätzlich ohne Offenlegung Ihrer Identität nutzen.

Des Weiteren verwenden wir keine Cookies oder ähnliche Technologien. Sicher haben Sie schon den Hinweis vermisst :)


Wir verwenden Fotos von unsplash sowie pixabay und danken: