Worum geht’s?

Ich will mal etwas aufklären, was Monitoring, Logging, Alerting und Sampling bedeutet, und mit ein paar Missverständnissen aufräumen.

Ein großer Haufen Datenmist

Sobald die Softwarelandschaft groß genug wird, ohne vorher über das Monitoring nachgedacht zu haben, möchte man das ab einem gewissen Zeitpunkt natürlich gerne haben. Man greift sich entweder die Logs von Servern manuell ab, oder lässt die Anwendungen Mails verschicken, oder irgend eine andere Lösung, die mehr schlecht als recht funktioniert. Man wirft alles in eine große Datenhalde und denkt sich… hm, ich habe doch jetzt alle Daten, dann kann ich ja endlich rauskriegen, was hier so Sache ist.

Das Problem ist jetzt, dass man alle Daten hat. Auch die, die eigentlich keinen interessieren, oder gar irreführend sind. Wenn die Applikationen ohnehin schon so gebaut sind, dass sie keine sinnvolle Möglichkeit bieten, Logs oder Metriken abgreifen zu können, heißt das in der Regel auch, dass die Logmeldungen und Metriken falsch gewählt sind, da sich offenbar keine großen Gedanken darum gemacht wurden.

Monitoring fängt bei der Anwendung an, nicht bei der Datenhalde, oder genauer gesagt dem System, was die Logs und Metriken auswerten soll. Es ist keine Kunst, eine große Datenhalde zu bauen, in die man sämtlichen Rest- und Sondermüll reinballert, den man in seinem Applikationszustand findet. Als Entwickler einer Anwendung muss ich mir Gedanken darüber machen, welche Logmeldungen und welche Metriken relevant sind, um Fehlerursachen erkennen und beheben zu können, ohne die Anwendung debuggen zu müssen, in gewisser Weise also Fernwartung.

Piep Piep Heartbeat

Wenn meine Anwendung hochverfügbar sein muss, dann brauche ich einen Heartbeat oder einen Watchdog. Ersterer ist in der Anwendung selbst implementiert, das heißt die Anwendung pingt in regelmäßigen Abständen das Monitoring an, und wenn der Heartbeat weg bleibt, ist was kaputt (es piept also einfach nur wie ein EKG und liefert sonst keine weiteren Informationen). Ein Watchdog ist einfach eine weitere Software, die die Anwendung überwacht und für diese den Heartbeat übernimmt, und die Software ggf. neu startet. Das blöde ist nur… wer überwacht den Watchdog? Und brauche ich wirklich noch eine Komponente die gewartet werden muss?

Wenn der Heartbeat funktioniert, ist schonmal ein kleiner Schritt getan: ich muss nicht mehr auf die Server schauen um festzustellen, ob meine Anwendung noch lebt.

Logging

Viele Leute verwechseln beim Monitoring gerne Logging mit Sampling. Beim Logging werden Prosa-Nachrichten eingesammelt (also sowas in der Art wie „Connection to XY timed out“), beim Sampling werden Metriken zur Auswertung eingesammelt (hier also sowas wie Anzahl der offenen Verbindungen zu Host XY, übertragene Datenmenge, Latenzen, etc.).

Das Logging dient ausschließlich dazu, Fehler nachvollziehen zu können, ohne auf den Server zu müssen. Wenn die Logging-Halde ordentlich aufgesetzt ist, lässt sich im Idealfall dann auch nachvollziehen, warum ein Server abgeraucht und nicht mehr erreichbar ist, da die Logs ja zentral vorgehalten werden. Damit das allerdings auch wirklich verwendbar ist, darf hier aber nicht alles weggeloggt werden, was vielleicht irgendwann mal interessant sein könnte. Stattdessen sollten hier nur Sachen geloggt werden, die potenziell zu Problemen führen, um auch a-priori Fehler vermeiden zu können. Für ein sinnvolles Logging werden eigentlich fast immer Ursache (also bspw. die Quelle eines Requests und der Request selbst) und Status (bspw. die Revision der geladenen Daten) benötigt. Alles andere sorgt nur dafür, dass man von Logs erschlagen wird.

Hier gilt halt auch der Grundsatz: So viel wie nötig, so wenig als möglich. Und nicht andersrum, wie es halt gerne verstanden wird.

Für das Logging auch relativ wichtig ist die „Severity“ der Meldungen. Um a-priori handeln zu können, ist es wichtig zu wissen, wie kritisch diese Nachrichten zu handhaben sind. Wenn mein Backend auf einmal etwas langsamer antwortet, ist das noch kein Grund den Feuerlöscher rauszuholen, aber wenn das Backend schwerwiegende Fehler erkennt, sollte man sofort handeln.

Die Severity lässt sich dabei anhand einiger einfacher Regeln feststellen (Quelle: http://docs.alerta.io/en/latest/conventions.html).

·         Critical – die Anwendung ist tot. Entweder meldet also die Anwendung, dass eines ihrer Backends tot ist, oder der Heartbeat einer Anwendung funktioniert nicht.

·         Major – Die Software lebt noch, allerdings sind Fehler nach außen hin sichtbar.

·         Minor – Die Software funktioniert an und für sich noch, allerdings nicht so wie sie sollte, da bspw. externe Quellen nicht erreichbar sind. Die Fehler sind nur intern sichtbar, und Kunden erhalten bspw. reduzierte Suchergebnisse.

·         Warning – Beinhaltet alles andere, was die Software feststellt, und potenziell zu Problemen führt.

·         Informational – Hier wird das Land des Debuggens betreten. Diese Meldungen dienen ausschließlich der Nachverfolgung und sind für ein Alerting komplett irrelevant. Diese sollten nur dann geloggt werden, wenn in die tiefere Analyse von Fehlern eingestiegen wird.

Alerts

Ich will an dieser Stelle zuallererst auf Alerta hinweisen, welches die Aggregation von Alerts übernimmt.

Und zuallernächst klären wir mal die Frage, was Alerting eigentlich heißt, und warum Logging kein Alerting ist.

Logging tritt wiederholt auf, d.h. beim Logging wird bspw. mehrfach geloggt, dass ein Backend nicht antwortet, oder Ressourcen nicht aktuell sind. In diesem Fall möchte ich nicht immer wieder darauf hingewiesen werden, denn obwohl es mehrere Logmeldungen sind, ist es nur ein einziger Fehler. Diese Aufgabe übernimmt u.A. Alerta, indem es Alert-Duplikate erkennt, und daraus nur einen einzigen Alert generiert.

Das erklärt auch, warum E-Mails eine extrem schlechte Wahl für Logs und Alerts sind: Ich muss mir jede einzelne Mail anschauen, um festzustellen, ob es zehn mal der gleiche Fehler ist, oder ob es sich um 10 unterschiedliche Fehler handelt. Eine übersichtliche Aggregation der Mails ist eigentlich unmöglich bzw. mit sehr viel Aufwand verbunden. Ich sag’s nochmal… Alerta!

Metriken & Sampling

Kommen wir jetzt mal dazu, was genau eine Metrik ausmacht. Eine Metrik ist eigentlich nur ein skalarer Wert zu einem bestimmten Zeitpunkt, mit dem in der Regel eine Einheit verbunden ist, z.B. könnte die aktuelle RAM-Nutzung mit der Einheit Bytes gemessen werden. Wird diese Metrik über einen Zeitraum regelmäßig gemessen, spricht man von einem Sampling.

Aber natürlich (wie sollte es anders sein) ist das das nicht ganz so einfach. Beim Sampling muss man zwischen zwei Qualitäten der Metrik unterscheiden, nämlich punktuellen Metriken und kontinuierlichen Metriken. Der Unterschied ist relativ einfach erklärt. Die RAM-Nutzung ist eine punktuelle Metrik, d.h., zu jedem Zeitpunkt des Samplings wird nur der aktuelle Momentanzustand aufgenommen, ich erhalte keinerlei Informationen darüber, was zwischen zwei Samplings vorgenommen wurde. Uns entgehen also sämtliche Informationen über die Auslastung zwischen zwei Samplings. In diesem Fall kommt (zumindest unter Linux) das Logging wieder ins Spiel wenn der OOM-Killer zuschlägt, um erkennen zu können, dass zwischen zwei harmlos aussehenden Samplings der RAM ausgeschöpft war und Linux mal was abgeschossen hat.

Im Gegensatz zu punktuellen Metriken gibt es da noch die kontinuierlichen Metriken. Mathematisch (ungenau) betrachtet ist das ganz einfach nur das Integral über eine Metrik, und wir greifen bei jedem Sampling dann diesen summierten Wert ab, und können dann per Ableitung bzw. Steigungswerterrechnung den Durchschnittswert der Metrik zwischen zwei Samplings ausrechnen. Klingt kompliziert, ist aber eigentlich ganz einfach. Nehmen wir zum Beispiel die Messung eines Requestdurchsatzes mit der Einheit req/s (Requests pro Sekunde). Anstatt dass wir nun den Momenandurchsatz abgreifen, greifen wir bei jedem Sampling stattdessen einfach die Gesamtzahl der bis dato bearbeiteten Requests ab. Wir können dann den durchschnittlichen Requestdurchsatz zwischen zwei Samplings errechnen, indem wir die beiden gemessenen Werte voneinander subtrahieren und anschließend durch die Zeitdifferenz zwischen den Samplings teilen, wir also die Sekantensteigung errechnen. Könnten wir die Samplingperiode beliebig verkleinern, würden wir schlussendlich bei der Differentiation einer Kurve landen.

Ein etwas Hirnknoten-reicheres Beispiel für eine kontinuierliche Metrik ist die Prozessorauslastung. Wir können an dieser Stelle die akkumulierte Rechenzeit eines Prozesses (in Sekunden) abgreifen. Wenn wir hier die Sekantensteigung ausrechnen (also Rechenzeit durch Samplingperiode teilen), erhalten wir eine einheitenlose Metrik, welche die durchschnittlich genutzten Cores einer CPU zwischen zwei Samplings ausdrückt.

In jedem Fall (wirklich in jedem Fall) ist es also besser, kontinuierliche Metriken aufzunehmen, da hier keine Informationen verloren gehen. Weiterhin ist darauf zu achten, keinerlei vorberechneten Metrik aufzunehmen, z.B. bereits die RAM-Nutzung in Prozent; das kann Client-Seitig bei Auswertung der Metriken erfolgen und verhindert den Verlust von Informationen.

Übrigens, wenn es um die Entscheidung geht, ob InfluxDB oder Prometheus, empfehle ich dringend Prometheus vorzuziehen. Ich konnte mit beiden Systemen arbeiten, und Prometheus ist InfluxDB einfach überlegen was die Client-seitige Auswertung von Metriken angeht. Viele Sachen sind in InfluxDB einfach nicht möglich bzw. nur mit sehr abenteuerlichen Konstrukten. Übrigens (wer es noch nicht gemerkt hat): Ein ELK-Stack ist eine Logging-Lösung, und nicht geeignet für die Aufnahme und Auswertung von Metriken.

Und wenn sie nicht gestorben sind...

Das ist doch jetzt länger geworden als gedacht, und trotzdem habe ich viele Aspekte nur oberflächlich abgehandelt. Zur Visualisierung von Metriken gibt es auch noch eine Menge zu sagen, ebenso zur Auswahl der richtigen Metriken, und noch einige andere Sachen die mir spontan nicht in den Sinn kommen.

Fragen? Anregungen? Ab in die Kommentare damit!

Leave a reply