Prometheus è un sistema di monitoraggio e alerting open source progettato per raccogliere ed elaborare metriche da applicazioni e infrastrutture. Funziona con un modello pull, inviando periodicamente richieste HTTP per raccogliere dati dai target configurati. I dati raccolti vengono archiviati localmente in un database personalizzato e interrogabili tramite il linguaggio PromQL. Prometheus è molto efficiente nel monitoraggio di sistemi distribuiti ed è ottimizzato per funzionare con tecnologie moderne come Docker e Kubernetes.
Figura 1:
In genere, le applicazioni non generano automaticamente metriche, ma richiedono l’integrazione di strumenti di misurazione nel codice sorgente da parte degli sviluppatori. Le Client Libraries semplificano questo processo: con poche righe di codice, è possibile definire le metriche e integrarle direttamente nel codice sorgente. Questa è chiamata direct instrumentation. Prometheus offre Client Libraries per linguaggi popolari come Go, Python, Java/JVM, Ruby e Rust. Esistono anche numerose librerie di terze parti per altri linguaggi come C#/.Net, Node.js, Haskell ed Erlang.
Non sempre è possibile accedere al codice sorgente del software per aggiungere codice e implementare la direct instrumentation. Un Exporter è un piccolo software installato insieme all’applicazione da cui si desidera ottenere le metriche. Riceve le richieste da Prometheus, raccoglie i dati dall’applicazione, li converte in un formato comprensibile a Prometheus e restituisce i risultati. Si può immaginare un exporter come un convertitore di dati tra l’applicazione e Prometheus. A differenza dell’integrazione diretta tramite Client Libraries, gli exporter utilizzano un tipo di misurazione diverso chiamato custom collectors o ConstMetrics.
Dopo aver integrato Prometheus nelle applicazioni e configurato gli exporter, Prometheus deve conoscere la posizione precisa delle applicazioni e degli exporter per poterli monitorare. In ambienti dinamici come il cloud, i servizi possono cambiare continuamente (vengono creati o eliminati), quindi non è possibile fornire un elenco statico di applicazioni ed exporter. Questo elenco diventerebbe rapidamente obsoleto, ed è per questo che è necessario il Service Discovery. Prometheus si integra con meccanismi di Service Discovery comuni come Kubernetes, EC2 e Consul, consentendogli di trovare automaticamente le applicazioni da monitorare. Se il sistema non utilizza questi servizi, Prometheus offre anche metodi di integrazione generici per altri sistemi.
Figura 2:
Dopo aver individuato i target da monitorare tramite Service Discovery e relabeling, Prometheus deve recuperare i dati da questi target. Lo fa inviando richieste HTTP, chiamate scrape, per raccogliere le metriche. Durante la raccolta dei dati, Prometheus registra anche alcune informazioni utili come: lo scrape è andato a buon fine? Quanto tempo ha impiegato? Lo scraping è configurato per avvenire regolarmente, in genere ogni 10-60 secondi per ogni target. Prometheus utilizza un modello pull, in cui recupera attivamente i dati dai target di monitoraggio (al contrario del modello push).
Prometheus archivia i dati direttamente sul proprio server, utilizzando un database personalizzato. Invece di costruire un complesso sistema di archiviazione distribuito, Prometheus opta per l’archiviazione locale per garantire un sistema più semplice e affidabile. La versione attuale di Prometheus 2.0 può raccogliere milioni di campioni di dati al secondo, sufficienti per monitorare migliaia di macchine con un singolo server Prometheus. Prometheus utilizza un algoritmo di compressione efficiente, con un rapporto di compressione di circa 1,3 byte per campione di dati. Si consiglia l’uso di SSD per migliorare le prestazioni, ma non è obbligatorio. Prometheus memorizza i dati solo sul server locale, quindi si è limitati dalla capacità del disco di quella macchina. Questo può essere un problema se si desidera archiviare i dati per lunghi periodi. Prometheus non offre una soluzione per l’archiviazione dei dati su più macchine (clustered storage). Tuttavia, dispone delle API remote read e remote write che consentono la connessione a sistemi di archiviazione esterni. In questo modo, è possibile interrogare i dati sia localmente che da remoto senza modificare le query.