ProHoster > Blog > Verwaltung > Einfache Arbeit mit komplexen Warnungen. Oder die Entstehungsgeschichte von Balerter
Einfache Arbeit mit komplexen Warnungen. Oder die Entstehungsgeschichte von Balerter
Jeder liebt Benachrichtigungen.
Natürlich ist es viel besser, benachrichtigt zu werden, wenn etwas passiert ist (oder behoben wurde), als sich die Diagramme anzusehen und nach Anomalien zu suchen.
Und dafür wurden viele Werkzeuge geschaffen. Alertmanager aus dem Prometheus-Ökosystem und vmalert aus der VictoriaMetrics-Produktgruppe. Zabbix-Benachrichtigungen und -Warnungen in Grafana. Selbstgeschriebene Skripte in Bash- und Telegram-Bots, die regelmäßig eine URL abrufen und Ihnen mitteilen, ob etwas nicht stimmt. Von allem viel.
Auch wir in unserem Unternehmen nutzten unterschiedliche Lösungen, bis wir auf die Komplexität bzw. die Unmöglichkeit stießen, komplexe, zusammengesetzte Warnungen zu erstellen. Was wir wollten und was wir letztendlich getan haben, liegt unter dem Strich. TLDR: So erschien das Open-Source-Projekt Balerter
Lange Zeit haben wir gut mit den in Grafana konfigurierten Alarmen gelebt. Ja, das ist nicht der beste Weg. Es wird immer empfohlen, spezielle Lösungen wie Alertmanager zu verwenden. Und wir haben auch mehrmals über einen Umzug nachgedacht. Und dann, nach und nach, wollten wir mehr.
Angenommen, ein bestimmtes Diagramm ist um XX % gefallen/angestiegen und befindet sich N Minuten lang im Vergleich zum vorherigen Zeitraum von M Stunden? Es scheint, dass Sie versuchen können, dies mit Grafana oder Alertmanager zu implementieren, aber es ist nicht ganz einfach. (Oder vielleicht ist es auch nicht möglich, das verrate ich jetzt nicht)
Noch komplizierter wird es, wenn die Alarmentscheidung auf der Grundlage von Daten aus verschiedenen Quellen getroffen werden muss. Live-Beispiel:
Wir überprüfen die Daten aus zwei Clickhouse-Datenbanken, vergleichen sie dann mit einigen Daten von Postgres und entscheiden uns für eine Warnung. Signalisieren oder abbrechen
Wir haben eine ganze Reihe ähnlicher Wünsche angesammelt, die uns zum Nachdenken über unsere Entscheidung anregen. Und dann haben wir versucht, die erste Liste der Anforderungen/Fähigkeiten dieses Dienstes zusammenzustellen, die noch nicht erstellt wurde.
Zugriff auf verschiedene Datenquellen. Zum Beispiel Prometheus, Clickhouse, Postgres
Senden Sie Benachrichtigungen an verschiedene Kanäle – Telegram, Slack usw.
Im Laufe des Nachdenkens wurde klar, dass ich keine deklarative Beschreibung wollte, sondern die Fähigkeit, Skripte zu schreiben
Ausführen von Skripten nach einem Zeitplan
Einfache Aktualisierung von Skripten ohne Neustart des Dienstes
die Möglichkeit, die Funktionalität irgendwie zu erweitern, ohne den Dienst aus Quellcodes neu zu erstellen
Diese Liste ist ungefähr und höchstwahrscheinlich nicht sehr genau. Einige Punkte haben sich geändert, andere sind gestorben. Alles wie gewöhnlich.
Eigentlich begann so die Geschichte von Balerter.
Ich versuche kurz zu beschreiben, was am Ende passiert ist und wie es funktioniert. (Ja, natürlich ist das noch nicht das Ende. Es gibt viele Pläne für die Produktentwicklung. Ich höre einfach bei heute auf.)
Wie funktioniert es?
Sie schreiben ein Skript in Lua, in dem Sie explizit Anfragen senden (an Prometheus, Clickhouse usw.). Man erhält Antworten und verarbeitet und vergleicht diese irgendwie. Dann schalten Sie eine Art Alarm ein/aus. Balerter selbst sendet eine Benachrichtigung an die von Ihnen konfigurierten Kanäle (E-Mail, Telegramm, Slack usw.). Das Skript wird in festgelegten Intervallen ausgeführt. Und... im Allgemeinen ist das alles)
Am besten zeigen Sie es anhand eines Beispiels:
-- @interval 10s
-- @name script1
local minRequestsRPS = 100
local log = require("log")
local ch1 = require("datasource.clickhouse.ch1")
local res, err = ch1.query("SELECT sum(requests) AS rps FROM some_table WHERE date = now()")
if err ~= nil then
log.error("clickhouse 'ch1' query error: " .. err)
return
end
local resultRPS = res[1].rps
if resultRPS < minResultRPS then
alert.error("rps-min-limit", "Requests RPS are very small: " .. tostring(resultRPS))
else
alert.success("rps-min-limit", "Requests RPS ok")
end
Was ist denn hier los:
Wir geben an, dass dieses Skript alle 10 Sekunden ausgeführt werden soll
Geben Sie den Namen des Skripts an (für die API, zur Anzeige in Protokollen, zur Verwendung in Tests)
Schließen Sie das Modul zur Protokollausgabe an
Schließen Sie ein Modul an, um mit dem Namen auf das Clickhouse zuzugreifen ch1 (Die Verbindung selbst wird in der Konfiguration konfiguriert)
Senden Sie eine Anfrage an Clickhouse
Im Fehlerfall zeigen wir eine Meldung im Protokoll an und beenden den Vorgang
Vergleichen Sie das Abfrageergebnis mit einer Konstante (in einem Live-Beispiel könnten wir diesen Wert beispielsweise aus der Postgres-Datenbank erhalten)
Alarm mit ID aktivieren oder deaktivieren rps-min-limit
Sie erhalten eine Benachrichtigung, wenn sich der Alarmstatus geändert hat
Das Beispiel ist recht einfach und verständlich. Allerdings können Drehbücher im wirklichen Leben natürlich recht langwierig und komplex sein. Es ist leicht, verwirrt zu werden und Fehler zu machen.
Daher ist ein logischer Wunsch gereift – Tests für Ihre Skripte schreiben zu können. Und in Version v0.4.0 erschien dies.
Skripte testen
Beispieltest für unser Skript aus obigem Beispiel:
-- @test script1
-- @name script1-test
test = require('test')
local resp = {
{
rps = 10
}
}
test.datasource('clickhouse.ch1').on('query', 'SELECT sum(requests) AS rps FROM some_table WHERE date = now()').response(resp)
test.alert().assertCalled('error', 'rps-min-limit', 'Requests RPS are very small: 10')
test.alert().assertNotCalled('success', 'rps-min-limit', 'Requests RPS ok')
Schritt für Schritt:
Geben Sie den Namen des Skripts an, für das der Test geschrieben wurde
Testname (für Protokolle)
Schließen Sie das Testmodul an
Wir sagen, welches Ergebnis für eine bestimmte Anfrage an das Clickhouse zurückgegeben werden soll ch1
Wir prüfen, ob die Warnung (Fehler) rps-min-limit mit der angegebenen Meldung aufgerufen wurde
Überprüfen Sie, ob die rps-min-limit-Warnung nicht deaktiviert wurde (Erfolg)
Was kann Balerter sonst noch tun?
Ich werde versuchen, auf die meiner Meinung nach wichtigsten Balerter-Fähigkeiten einzugehen. Alles im Detail können Sie auf der offiziellen Website sehen https://balerter.com
Daten empfangen von
Clickhouse
Postgres
mysql
Prometheus
loki
Senden Sie Benachrichtigungen an Kanäle
locker
Telegram mit
syslog
notify (UI-Benachrichtigungen auf Ihrem Computer)
E-Mail
Zwietracht
Erstellen Sie Diagramme basierend auf Ihren Daten, laden Sie das Bild auf einen S3-kompatiblen Speicher hoch und hängen Sie es an Benachrichtigungen an (Beispiel mit Bildern)
ermöglicht den Datenaustausch zwischen Skripten – globale Schlüssel-/Wertspeicherung
Schreiben Sie Ihre eigenen Bibliotheken in Lua und verwenden Sie sie in Skripten (standardmäßig werden Lua-Bibliotheken für die Arbeit mit JSON und CSV bereitgestellt).
Senden Sie HTTP-Anfragen von Ihren Skripten (und erhalten Sie natürlich Antworten)
stellt eine API bereit (noch nicht so funktionsfähig, wie wir es gerne hätten)
exportiert Metriken im Prometheus-Format
Was möchten Sie sonst noch tun können?
Es ist bereits klar, dass Benutzer und wir die Möglichkeit haben möchten, den Start von Skripten mithilfe der Syntax zu steuern cron. Dies wird vor Version v1.0.0 erfolgen
Ich würde gerne mehr Datenquellen und Benachrichtigungsübermittlungskanäle unterstützen. Beispielsweise wird jemand MongoDB definitiv vermissen. Elastic Search für einige. Senden Sie SMS und/oder telefonieren Sie mit Ihrem Mobiltelefon. Wir möchten Skripte nicht nur aus Dateien, sondern beispielsweise auch aus einer Datenbank empfangen können. Letztendlich wollen wir eine benutzerfreundlichere Website und eine bessere Dokumentation des Projekts.
Irgendjemandem fehlt immer etwas) Hier verlassen wir uns auf die Anfrage der Community, um Prioritäten richtig zu setzen. Und zur Hilfe der Community, alles zu verwirklichen
Abschließend
Wir gebrauchen Balerter Ich habe es jetzt schon eine ganze Weile. Dutzende Skripte schützen unseren Seelenfrieden. Ich hoffe, dass diese Arbeit für jemand anderen nützlich sein wird.