
A tutti piacciono gli avvisi.
Certo, è decisamente meglio ricevere una notifica quando accade qualcosa (o si ripara) piuttosto che rimanere a fissare grafici e cercare anomalie.
Sono stati creati molti strumenti per questo. Alertmanager dall'ecosistema di Prometheus e vmalert dalla suite di prodotti VictoriaMetrics. Notifiche di Zabbix e avvisi in Grafana. Script personalizzati in bash e bot Telegram che periodicamente sollecitano un certo URL e segnalano se qualcosa non va. C'è davvero una vasta scelta.
Anche nella nostra azienda abbiamo utilizzato diverse soluzioni, fino a quando ci siamo imbattuti nella complessità o, più precisamente, nell'impossibilità di creare avvisi complessi e compositi. Quello che volevamo e ciò che alla fine abbiamo realizzato è riportato di seguito. TLDR: così è nato il progetto open source
Per un lungo periodo ci siamo trovati bene con gli avvisi configurati in Grafana. Sì, non è la soluzione migliore. È sempre consigliato usare qualche soluzione specializzata, come Alertmanager. Anche noi abbiamo guardato verso un potenziale migrazione più di una volta. Poi, lentamente, abbiamo iniziato a desiderare di più.
Dire quando un dato grafico è sceso/a salito/a del XX% e rimane lì da N minuti rispetto a un periodo precedente di M ore? Sembra che si possa provare a realizzarlo con Grafana o Alertmanager, ma non è molto semplice. (O forse non si può, non so dirti ora)
Tutto diventa ancora più complicato quando la decisione di allerta deve essere presa in base a dati provenienti da diverse fonti. Un esempio concreto:
Controlliamo i dati da due database Clickhouse, quindi li confrontiamo con alcuni dati da Postgres e prendiamo una decisione riguardo all'allerta. Segnalare o annullare
Abbiamo accumulato così tante richieste simili che abbiamo iniziato a pensare a una soluzione propria. Così abbiamo provato a stilare un primo elenco di requisiti e funzionalità di questo servizio, che ancora non esiste
collegarsi a diverse fonti di dati. Ad esempio, Prometheus, Clickhouse, Postgres
inviare allerta a vari canali — telegram, slack, ecc.
nel corso della riflessione è diventato chiaro che si preferiva non una descrizione dichiarativa, ma la possibilità di scrivere script
eseguire script secondo una programmazione
facile aggiornamento degli script senza riavviare il servizio
possibilità di espandere le funzionalità senza ricompilare il servizio dai codici sorgente
Questo è un elenco indicativo e probabilmente non molto preciso. Alcuni punti sono stati modificati, altri sono stati abbandonati. Tutto come al solito.
In effetti, è proprio così che è iniziata la storia di Balerter.

Cercherò di descrivere brevemente cosa è successo e come funziona. (Sì, certo, non è la fine. Ci sono molti piani per lo sviluppo del prodotto. Mi fermerò solo al giorno di oggi)
Come funziona?
Scrivete uno script in Lua, dove inviate esplicitamente richieste (a Prometheus, Clickhouse, ecc.). Ricevete risposte e in qualche modo le elaborate e le confrontate. Dopodiché attivate/disattivate un allerta. Balerter invierà autonomamente notifiche ai canali che avete configurato (Email, telegram, slack, ecc.). Lo script viene eseguito con una periodicità prescelta. E... questo è tutto)
La migliore spiegazione è con un esempio:
-- @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("errore nella query clickhouse 'ch1': " .. err)
return
end
local resultRPS = res[1].rps
if resultRPS < minRequestsRPS then
alert.error("rps-min-limit", "Le richieste RPS sono molto basse: " .. tostring(resultRPS))
else
alert.success("rps-min-limit", "Le richieste RPS sono ok")
end Cosa sta succedendo qui:
indichiamo che questo script deve essere eseguito ogni 10 secondi
indichiamo il nome dello script (per l'API, per la visualizzazione nei log, per utilizzarlo nei test)
colleghiamo il modulo per l'output dei log
colleghiamo il modulo per accedere a ClickHouse con nome
ch1(la connessione viene configurata nel file di configurazione)inviamo la richiesta a ClickHouse
in caso di errore, registriamo un messaggio nel log e usciamo
confrontiamo il risultato della richiesta con una costante (in un esempio reale potremmo ottenere questo valore, ad esempio, da un database Postgres)
attiviamo o disattiviamo l'alert con ID
rps-min-limitriceverai una notifica se lo stato dell'alert cambia
L'esempio è piuttosto semplice e comprensibile. Tuttavia, nella vita reale, gli script possono essere piuttosto ramificati e complessi. È facile perdersi e commettere errori.
Pertanto, è nata la necessità logica di poter scrivere test per i propri script. E con la versione v0.4.0 è stata introdotta questa funzionalità.
Testing degli script
Ecco un esempio di test per il nostro script dall'esempio precedente:
-- @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')Passo dopo passo:
indichiamo il nome dello script per il quale è stato scritto il test
nome del test (per i log)
colleghiamo il modulo di test
specifichiamo quale risultato deve essere restituito per una determinata richiesta al ClickHouse
ch1verifichiamo che sia stato chiamato l'allerta (error) rps-min-limit con il messaggio specificato
verifichiamo che l'allerta rps-min-limit non sia stata disattivata (success)
Cosa può fare ancora Balerter?
Cercherò di toccare le capacità più importanti di Balerter. È possibile vedere tutto in dettaglio sul sito ufficiale
ottenere dati da
clickhouse
postgres
mysql
prometheus
loki
inviare notifiche ai canali
slack
telegram
syslog
notify (notifiche UI sul tuo computer)
email
discord
costruire grafici dai tuoi dati, caricare immagini in un archivio compatibile con S3 e allegarle alle notifiche ()
permette di scambiare dati tra script — memoria globale Key/Value
scrivere le proprie librerie in Lua e utilizzarle negli script (sono incluse per impostazione predefinita librerie lua per lavorare con json, csv)
inviare richieste HTTP dai propri script (e ricevere risposte, ovviamente)
fornisce un'API (ancora non così funzionale come vorremmo)
esporta metriche nel formato Prometheus
Cosa vorresti ancora sapere?
È già chiaro che gli utenti e noi vogliamo la possibilità di gestire l'esecuzione degli script tramite la sintassi cron. Questo sarà implementato prima della versione v1.0.0
Vorremmo supportare più fonti di dati e canali di consegna delle notifiche. Ad esempio, a qualcuno mancherà sicuramente MongoDB. A qualcun altro Elastic Search. Inviare SMS e/o effettuare chiamate ai cellulari. Vogliamo essere in grado di ricevere script non solo da file, ma ad esempio anche da un database. In definitiva, desideriamo un sito più comodo per il progetto e una documentazione migliore.
C'è sempre qualcosa che manca a qualcuno) Qui speriamo nel feedback della comunità per stabilire correttamente le priorità. E ci aspettiamo l'aiuto della comunità per realizzare tutto.
In conclusione
Utilizziamo è da un po' che ce l'abbiamo. Decine di script vigilano sulla nostra tranquillità. Spero che questo lavoro possa essere utile a qualcun altro.
E benvenuti con i vostri Issue e PR.
Fonte: habr.com
