Ti invitiamo a prendere visione della trascrizione della relazione di Roman Khavronenko "ExtendedPromQL"


Brevemente su di me. Mi chiamo Roman. Lavoro in CloudFlare e vivo a Londra. Ma sono anche maintainer di VictoriaMetrics.
E sono l'autore per Grafana e è un piccolo proxy per ClickHouse.

Inizieremo con la prima parte, che si chiama "Le difficoltà della traduzione", in cui parlerò del fatto che qualsiasi lingua, o anche semplicemente il linguaggio comunicativo, è estremamente importante. Perché è ciò che usiamo per trasmettere pensieri ad un'altra persona o a un sistema, come formuliamo una richiesta. La gente su internet discute su quale lingua sia migliore: java o un'altra. Personalmente ho deciso che bisogna scegliere in base al compito, perché tutto questo è specifico.

Cominciamo dall'inizio. Cos'è PromQL? PromQL è il Prometheus Query Language. È il modo in cui formiamo le query in Prometheus per ottenere dati sulle serie temporali.

Cosa sono i dati delle serie temporali? Se lo prendiamo letteralmente, ci sono tre parametri.
Essi sono:
- A cosa stiamo guardando.
- Quando lo stiamo guardando.
- E quale valore mostra.

Se guardiamo questo grafico (questo grafico proviene dal mio telefono, che mostra le statistiche dei miei passi), possiamo rapidamente rispondere a queste domande.
Stiamo guardando ai passi. Vediamo un valore e vediamo il tempo in cui lo stiamo osservando. Cioè, guardando questo grafico è facile dire che domenica ho fatto circa 15.000 passi. Questi sono dati delle serie temporali.

Ora proviamo a "scomporli" (trasformarli) in un altro modello di dati in forma di tabella. Qui abbiamo anche ciò a cui stiamo guardando. Ho aggiunto alcuni dati extra che chiameremo metadati, cioè, non sono stati fatti da me, ma da due persone, diciamo, Jay e Silent Bob. Quello è ciò a cui stiamo guardando; cosa mostra e quando mostra quel valore.

Ora proviamo a memorizzare tutti questi dati in un database. Per esempio, ho preso la sintassi di ClickHouse. Qui creiamo una tabella chiamata "Steps", cioè, ciò a cui stiamo guardando. Qui c'è il tempo in cui lo stiamo osservando; cosa mostra e alcuni metadati, dove memorizzeremo chi sono: Jay e Silent Bob.

E per cercare di visualizzare tutto questo, useremo Grafana, perché, prima di tutto, è bello.

Utilizzeremo anche questo plugin. Ci sono due motivi per cui. Il primo è che l'ho scritto io. E so bene quanto sia difficile estrarre dati di serie temporali da ClickHouse per mostrarli in Grafana.

Mostreremo nel Graph Panel. È il pannello più popolare in Grafana, che mostra la dipendenza dei valori nel tempo, quindi abbiamo bisogno solo di due parametri.

Scriviamo la query più semplice: come mostrare le statistiche dei passi in Grafana, memorizzando questi dati in ClickHouse, nella tabella che abbiamo creato. Scriviamo quindi una query semplice. Selezioniamo dai passi. Selezioniamo il valore e selezioniamo il tempo di questi valori, cioè gli stessi tre parametri di cui abbiamo parlato.

Ed ecco il grafico che otterremo. Chi sa perché è così strano?

Esatto, dobbiamo ordinare per tempo.

E alla fine otterremo un grafico un po' migliore, ma ancora strano. Chi sa perché? Giusto, ci sono due partecipanti, e in Grafana forniamo due serie temporali, perché se analizziamo di nuovo il modello dei dati, ogni serie temporale è una combinazione unica di nome e tutte le chiavi-valori delle etichette.

Quindi dobbiamo scegliere una persona specifica. Scegliamo Jay.

E disegniamo di nuovo. Ora il grafico sembra reale. Ora è un grafico normale e tutto funziona bene.

E probabilmente sapete come fare più o meno la stessa cosa, ma in Prometheus attraverso PromQL. Circa in questo modo. Un po' più semplice. E ancora lo divideremo tutto. Abbiamo preso Steps. E filtriamo per Jay. Qui non specifichiamo che abbiamo bisogno di ottenere il valore e non selezioniamo il tempo.

Ora proviamo a calcolare la velocità di movimento di Jay o Silent Bob. In ClickHouse dovremo fare runningDifference, cioè calcolare la differenza tra coppie di punti e dividerle per il tempo, per ottenere la velocità esatta. La query assomiglierà a qualcosa del genere.

E mostrerà valori simili a questi, cioè Silent Bob o Jay fanno circa 1,8 passi al secondo.

E in Prometheus sapete anche come farlo. È molto più semplice rispetto a prima.
E per rendere tutto ciò ancora più semplice da fare in Grafana, ho aggiunto un wrapper del genere, che assomiglia molto a PromQL. Si chiama Rate Macros, o come preferite chiamarlo. In Grafana si usa semplicemente "rate", ma da qualche parte in profondità si trasforma in una grande query. E non c'è bisogno neanche di guardarla, è lì da qualche parte, ma risparmi un sacco di tempo, perché scrivere tali enormi query SQL è sempre oneroso. Puoi facilmente commettere un errore e poi non capire a lungo cosa stia succedendo.

Ecco una query che nemmeno è riuscita a stare in un solo slide e ho dovuto dividerla in due colonne. Questa è anche una query in ClickHouse, che fa lo stesso rate, ma su entrambe le serie temporali: sia su Silent Bob che su Jay, per avere due serie temporali nel nostro pannello. E questo è già molto complicato, a mio avviso.

E per Prometheus sarà sum (rate). Per ClickHouse ho creato un macro separato che si chiama RateColumns, che appare come una query in Prometheus.

Abbiamo dato un'occhiata e sembrava che PromQL fosse fantastico, ma ha sicuramente delle limitazioni.
Essi sono:
- SELECT limitato.
- JOIN limitati.
- Nessun supporto per HAVING.
E se hai lavorato a lungo con esso, sai che a volte è molto difficile fare qualcosa in PromQL, mentre in SQL si può fare quasi tutto, perché tutte queste opzioni che abbiamo appena discusso possono essere realizzate in SQL. Ma sarebbe comodo usarle? Questo mi fa pensare che non sempre il linguaggio più potente sia il più comodo.

Pertanto, a volte è necessario scegliere il linguaggio in base alle esigenze. È come la battaglia tra Batman e Superman. È chiaro che Superman è più forte, ma Batman è riuscito a sconfiggerlo perché è più pratico e sapeva esattamente cosa stava facendo.

E la parte successiva è l'estensione di PromQL.

Ancora su VictoriaMetrics. Cos'è VictoriaMetrics? È un database di serie temporali, è open source, distribuiamo le sue versioni singole e in cluster. Secondo i nostri benchmark, è il più veloce attualmente disponibile sul mercato e offre anche una compressione simile, cioè persone reali riportano compressioni di circa 0,4 byte per punto, mentre per Prometheus è di 1,2-1,4.
Non supportiamo solo Prometheus. Supportiamo InfluxDB, Graphite, OpenTSDB.
È possibile "scrivere" dentro di noi, cioè è possibile trasferire dati storici.
E in più lavoriamo perfettamente con Prometheus e Grafana, cioè supportiamo il motore PromQL. E in Grafana puoi semplicemente cambiare l'endpoint di Prometheus in VictoriaMetrics e tutte le tue dashboard funzioneranno come prima.
Ma puoi utilizzare anche funzioni aggiuntive fornite da VictoriaMetrics.
Darò rapidamente uno sguardo alle funzionalità che abbiamo aggiunto.

Ometti il parametro dell'intervallo – puoi saltare il parametro dell'intervallo in Grafana. Quando non vuoi ottenere grafici strani durante lo zoom in/out nel pannello, è consigliabile utilizzare la variabile $__interval. Questa è una variabile interna di Grafana che seleziona autonomamente l'intervallo di dati. E VictoriaMetrics può capire da sola quale deve essere questo intervallo. Non dovrai aggiornare tutte le tue query. Sarà molto più facile.

La seconda funzione è il riferimento all'intervallo. Puoi utilizzare questo intervallo nelle tue espressioni. Puoi moltiplicare, dividere, passare e fare riferimento ad esso.

Poi abbiamo la famiglia delle funzioni rollup. Le funzioni rollup trasformano qualsiasi tuo time series in tre time series separate: min, max e avg. Considero che sia molto comodo, perché a volte può mostrare alcuni outliers (anomalia) e imprecisioni.

E se semplicemente fai irate o rate, probabilmente potresti trascurare alcuni casi in cui il time series si comporta diversamente da quanto previsto. Con questa funzione è molto più semplice vedere, ad esempio, che il max si discosta notevolmente dall’avg.

Avanti, la variabile default. Default significa quale valore dobbiamo disegnare in Grafana, se non abbiamo un time series in quel momento. Quando accade? Supponiamo che tu stia esportando una qualche metrica sugli errori. E hai un'app così fantastica che, quando hai iniziato, non hai errori e nemmeno errori nei tre orari successivi o anche nel giorno successivo. E hai cruscotti che mostrano il rapporto tra successi ed errori. E ti mostreranno nulla, perché non hai una metrica sugli errori. Ma in default puoi specificare qualsiasi cosa.

Keep_last_Value – mantiene l'ultimo valore della metrica, se è scomparsa. Se Prometheus non riesce a trovarla entro 5 minuti dalla successiva scansione, ricorderemo il suo ultimo valore e i tuoi grafici non si romperanno di nuovo.

Scrape_interval – mostra con quale frequenza Prometheus raccoglie i dati sulla tua metrica, che frequenza ha. Qui puoi vedere un salto, ad esempio.

Label replace – è una funzione popolare. Ma riteniamo che sia un po' complessa, perché richiede molti argomenti. E non solo devi ricordare 5 argomenti, ma devi anche ricordarne l'ordine.

Quindi, perché non semplificarli? Cioè, suddividerli in funzioni più piccole con una sintassi chiara.

E ora viene la parte interessante. Perché consideriamo questo PromQL esteso? Perché supportiamo le Common Table Expressions. Puoi scansionare il codice QR (), guardare i link con esempi, con playground, dove puoi eseguire query direttamente in VictoriaMetrics senza installarla, semplicemente nel browser.

E che cos'è esattamente? Questa query in alto è una query piuttosto popolare. Penso che in qualsiasi dashboard di molte aziende tu stia utilizzando lo stesso filtro per tutto. Di solito è così. Ma quando devi aggiungere un nuovo filtro, devi aggiornare ogni pannello, oppure scaricare la dashboard, aprirla in JSON, fare trova e sostituisci, il che richiede tempo. Perché non mantenere quel valore in una variabile e riutilizzarlo? Questo sembra, dal mio punto di vista, molto più semplice e comprensibile.

Ad esempio, quando devo aggiornare i filtri in Grafana in tutte le query, e la dashboard può essere enorme o potrebbero esserci anche più dashboard. E come vorrei risolvere questo problema in Grafana?

Affronto questo problema in questo modo: creo un commonFilter e in esso definisco questo filtro, poi lo riutilizzo nelle query. Ma se ora fai lo stesso, non funzionerà, perché Grafana non ti consente di usare variabili all'interno delle variabili di query. Ed è un po' strano.

E quindi ho creato un'opzione che lo consente. E se sei interessato o desideri una funzionalità del genere, supportami o metti un non mi piace se questa idea non ti piace.

Proseguendo con PromQL esteso. Qui definiamo non solo una variabile, ma un'intera funzione. E la chiamiamo ru (resource usage). Questa funzione accetta le risorse disponibili, un limite di risorse e un filtro. Sembrerebbe che la sintassi sia tutta semplice. Ed è molto facile usare questa funzione e calcolare la percentuale di memoria disponibile. Cioè, quanta memoria abbiamo, qual è il limite e come filtrare. Sembra molto più comodo se scrivessi tutto questo, riutilizzando gli stessi filtri, perché si trasformerebbe in una grande e complessa query.

Ecco un esempio di una richiesta così grande. Proviene dal cruscotto ufficiale di NodeExporter per Grafana. Ma non capisco bene cosa stia succedendo qui. Cioè, certo, lo capisco se ci si fa attenzione, ma il numero di parentesi può subito ridurre la motivazione a capire cosa succede. E perché non renderlo più semplice e chiaro?

Ad esempio, in questo modo, evidenziando le cose o le parti significative in variabili. E poi effettuando la propria matematica di base. Questo è già più simile alla programmazione, è quello che vorrei vedere in futuro in Grafana.

Ecco un secondo esempio di come potremmo semplificare ulteriormente, se avessimo già questa funzione ru, che è già disponibile direttamente in VictoriaMetrics. E quindi si passa semplicemente il valore memorizzato nella cache che si è dichiarato nel CTE.

Ho già parlato di quanto sia importante utilizzare il linguaggio di programmazione giusto. E probabilmente, in ogni azienda, si fanno cose diverse in Grafana. E probabilmente concedete anche l'accesso a Grafana ai vostri sviluppatori, che fanno qualcosa di loro. E tutti lo fanno in modo un po' diverso. Sarebbe bello se si potesse fare in modo uniforme, cioè ridurlo a uno standard comune.
Supponiamo che tu abbia non solo ingegneri di sistema, magari hai anche esperti, devops o SRE. Magari hai esperti che sanno cos'è il monitoraggio, sanno cos'è Grafana, cioè lavorano con questo da anni e sanno esattamente come fare le cose nel modo giusto. E lo hanno già scritto 100 volte e spiegato a tutti, ma per qualche motivo nessuno ascolta.
E se potessero mettere direttamente queste conoscenze in Grafana, affinché altri utenti potessero riutilizzare le funzioni? E se fosse necessario calcolare la percentuale di memoria libera, semplicemente applicerebbero la funzione. E se i creatori degli exporter, insieme al loro prodotto, fornissero anche un insieme di funzioni su come lavorare con le loro metriche, perché sanno esattamente di che metriche si tratta e come calcolarle correttamente?
In realtà, questo non esiste. Questo l'ho fatto io stesso. È il supporto delle librerie in Grafana. Supponiamo che i ragazzi che hanno fatto NodeExporter abbiano creato ciò di cui ho parlato. E abbiano anche fornito un insieme di funzioni.

Cioè, appare più o meno così. Colleghi questa libreria in Grafana, apri il modo di modifica e qui c'è scritto molto semplicemente in JSON come lavorare con questa metrica. Cioè, un insieme di funzioni, la loro descrizione e in cosa si traducono.

Secondo me, questo potrebbe essere utile, perché così in Grafana scriveresti semplicemente in questo modo. E Grafana ti 'dice' che c'è una certa funzione di una certa libreria – usiamola. Mi sembra che sarebbe davvero fantastico.

Un po' su VictoriaMetrics. Facciamo molte cose interessanti. Leggi i nostri articoli sulla compressione, sulle nostre competizioni con altre applicazioni di dati a serie temporale, la nostra spiegazione su come lavorare con PromQL, perché ci sono ancora molti principianti, e anche sulla scalabilità verticale e sulla competizione con Thanos.

Domande:
Inizierò la mia domanda con una semplice storia di vita. Quando ho iniziato a usare Grafana per la prima volta, ho scritto una query molto convincente di cinque righe. Alla fine è venuto fuori un grafico molto convincente. Questo grafico è quasi entrato in produzione. Ma a un esame più attento, si è scoperto che questo grafico mostra un'assurdità assoluta, senza alcun legame con la realtà, anche se i numeri rientrano nell'intervallo che ci aspettavamo di vedere. E la mia domanda è: abbiamo le librerie, abbiamo le funzioni, ma come scriviamo test per Grafana? Hai scritto una query complessa su cui dipende una decisione aziendale – ordinare un vero contenitore di server o non ordinare. E come sappiamo che questa funzione, che disegna il grafico, assomiglia alla verità. Grazie.
Grazie per la domanda. Ci sono due parti. La prima – ho l'impressione, basandomi sulla mia esperienza, che la maggior parte degli utenti, quando guarda i propri grafici, non capisce cosa stiano mostrando. Per qualche motivo, le persone sono molto brave a inventare scuse per qualsiasi anomalia che si verifica nei grafici, anche se è un errore all'interno della funzione. E la seconda parte – mi sembra che l'utilizzo di funzioni come queste si adattasse molto meglio alla soluzione del tuo problema, piuttosto che ogni tuo sviluppatore faccia la propria pianificazione della capacità e commetta errori con una certa probabilità.
Come verificare?
Come verificare? Probabilmente, non si può.
Sotto forma di test in Grafana.
Che c'entra Grafana? Grafana traduce questa query direttamente nel DataSource.
Aggiungendo un po' ai parametri.
No, in Grafana non vengono aggiunti elementi. Ci possono essere parametri GET, come ad esempio step. Non è specificato esplicitamente, ma puoi sovrascriverlo, puoi anche non farlo, ma viene aggiunto automaticamente. Qui non potrai scrivere dei test. Penso che non sia il caso di fare affidamento su Grafana come fonte di verità.
Grazie per la relazione! Grazie per la compressione! Hai menzionato il mapping della variabile nel grafico, che in Grafana non si può utilizzare una variabile dentro un'altra variabile. Capisci a cosa mi riferisco?
Sì.
Era inizialmente un problema quando volevo creare un alert in Grafana. E lì bisogna fare alert per ogni singolo host. Quella cosa che hai fatto, funziona per gli alert in Grafana?
Se Grafana non gestisce le variabili in modo diverso, allora sì, funzionerà. Ma il mio consiglio è di non usare affatto l'alerting in Grafana, è meglio utilizzare Alertmanager.
Sì, lo utilizzo, ma semplicemente in Grafana è sembrato più facile configurarli, ma grazie per il consiglio!
Fonte: habr.com
