Lavoro facile con avvisi complessi. O la storia di Balerter
Tutti amano gli avvisi.
Naturalmente, è molto meglio essere avvisati quando qualcosa è successo (o è stato risolto) piuttosto che sedersi e guardare i grafici e cercare anomalie.
E per questo sono stati creati molti strumenti. Alertmanager dell'ecosistema Prometheus e vmalert del gruppo di prodotti VictoriaMetrics. Notifiche e avvisi Zabbix in Grafana. Script autoprodotti in bash e bot di Telegram che periodicamente recuperano alcuni URL e ti dicono se qualcosa non va. Molto di tutto.
Anche noi nella nostra azienda abbiamo utilizzato soluzioni diverse fino a incappare nella complessità, o meglio, nell’impossibilità di creare alert complessi e compositi. Ciò che volevamo e ciò che abbiamo finito per fare è al di sotto del taglio. TLDR: Ecco come è apparso il progetto open source Balerter
Per molto tempo abbiamo convissuto bene con gli avvisi configurati in Grafana. Sì, questo non è il modo migliore. Si consiglia sempre di utilizzare alcune soluzioni specializzate, come Alertmanager. E abbiamo anche pensato di spostarci più di una volta. E poi, a poco a poco, ne volevamo di più.
Diciamo quando un certo grafico è sceso/aumentato del XX% ed è rimasto lì per N minuti rispetto al periodo precedente di M ore? Sembra che tu possa provare a implementarlo con Grafana o Alertmanager, ma non è del tutto semplice. (O forse non è possibile, non lo dirò adesso)
Le cose si complicano ancora di più quando la decisione di allertare deve essere presa sulla base di dati provenienti da fonti diverse. Esempio dal vivo:
Controlliamo i dati di due database Clickhouse, quindi li confrontiamo con alcuni dati di Postgres e decidiamo di inviare un avviso. Segnalare o annullare
Abbiamo accumulato molti desideri simili affinché potessimo riflettere sulla nostra decisione. E poi abbiamo provato a stilare un primo elenco di requisiti/capacità di questo servizio, che ancora non è stato creato.
accedere a diverse fonti di dati. Ad esempio, Prometeo, Clickhouse, Postgres
inviare avvisi a vari canali: Telegram, Slack, ecc.
nel processo di riflessione, è diventato chiaro che non volevo una descrizione dichiarativa, ma la capacità di scrivere script
esecuzione di script secondo una pianificazione
facile aggiornamento degli script senza riavviare il servizio
la capacità di espandere in qualche modo la funzionalità senza ricostruire il servizio dai codici sorgente
Questo elenco è approssimativo e molto probabilmente non molto accurato. Alcuni punti sono cambiati, altri sono morti. Tutto è come al solito.
In realtà è così che è iniziata la storia di Balerter.
Proverò a descrivere brevemente cosa è successo alla fine e come funziona. (Sì, certo, questa non è la fine. Ci sono molti piani per lo sviluppo del prodotto. Mi fermerò solo a oggi)
Come funziona?
Scrivi uno script in Lua in cui invii esplicitamente richieste (a Prometheus, Clickhouse, ecc.). Ricevi risposte e in qualche modo le elabori e le confronti. Quindi attiva/disattiva una sorta di avviso. Balerter stesso invierà una notifica ai canali che hai configurato (e-mail, telegramma, slack, ecc.). Lo script viene eseguito a intervalli specificati. E... in generale, questo è tutto)
È meglio mostrarlo 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("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
Cosa sta succedendo qui:
indichiamo che questo script dovrebbe essere eseguito ogni 10 secondi
indicare il nome dello script (per le API, per la visualizzazione nei log, per l'utilizzo nei test)
collegare il modulo per l'emissione dei protocolli
collega un modulo per accedere alla clickhouse con il nome ch1 (la connessione stessa è configurata nella configurazione)
invia una richiesta a clickhouse
in caso di errore, visualizziamo un messaggio nel log e usciamo
confrontare il risultato della query con una costante (in un esempio dal vivo, potremmo ottenere questo valore, ad esempio, dal database Postgres)
abilitare o disabilitare l'avviso con ID rps-min-limit
riceverai una notifica se lo stato dell'avviso è cambiato
L'esempio è abbastanza semplice e comprensibile. Tuttavia, ovviamente, nella vita reale gli script possono essere piuttosto lunghi e complessi. È facile confondersi e commettere errori.
Pertanto, è maturato un desiderio logico: poter scrivere test per i tuoi script. E nella versione v0.4.0 questo è apparso.
Testare gli script
Test di esempio per il nostro script dall'esempio sopra:
-- @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')
I passaggi:
indicare il nome dello script per il quale è scritto il test
nome del test (per i log)
collegare il modulo di test
diciamo quale risultato dovrebbe essere restituito per una richiesta specifica alla clickhouse ch1
controlliamo che sia stato richiamato l'avviso (errore) rps-min-limit con il messaggio specificato
verificare che l'avviso limite minimo rps non sia stato disabilitato (successo)
Cos’altro può fare Balerter?
Cercherò di toccare le abilità più importanti, secondo me, di Balerter. Potete vedere tutto nel dettaglio sul sito ufficiale https://balerter.com
ricevere dati da
clickhouse
Postgres
mysql
Prometeo
Loki
inviare notifiche ai canali
allentato
Telegram
syslog
notifica (notifiche dell'interfaccia utente sul computer)
email
discordia
crea grafici basati sui tuoi dati, carica l'immagine su uno spazio di archiviazione compatibile con S3 e allegala alle notifiche (Esempio con immagini)
consente di scambiare dati tra script: archiviazione chiave/valore globale
scrivi le tue librerie in Lua e usale negli script (per impostazione predefinita, le librerie lua vengono fornite per lavorare con json, csv)
invia richieste HTTP dai tuoi script (e ricevi risposte, ovviamente)
fornisce un'API (non ancora funzionale come vorremmo)
esporta le metriche in formato Prometheus
Cos'altro ti piacerebbe poter fare?
È già chiaro che noi e gli utenti vogliamo la possibilità di controllare l'avvio degli script utilizzando la sintassi cron. Questa operazione verrà eseguita prima della versione v1.0.0
Vorrei supportare più origini dati e canali di recapito delle notifiche. Ad esempio, a qualcuno mancherà sicuramente MongoDB. Cercane alcuni elastici. Invia SMS e/o effettua chiamate sul tuo cellulare. Vogliamo poter ricevere script non solo da file, ma anche, ad esempio, da un database. Alla fine, vogliamo un sito web più user-friendly e una migliore documentazione per il progetto.
A qualcuno manca sempre qualcosa) Qui ci affidiamo alla richiesta della comunità per stabilire correttamente le priorità. E all'aiuto della comunità per realizzare tutto
insomma
Noi usiamo Balerter Ce l'ho ormai da un bel po' di tempo. Decine di script proteggono la nostra tranquillità. Spero che questo lavoro possa essere utile a qualcun altro.