Al giorno d’oggi, Apache Kafka è uno dei software più utilizzati nell’IT. È ovunque, è uno standard de facto per l’event streaming ed è ampiamente adottato nelle grandi aziende. Il progetto Apache Kafka afferma che Kafka è utilizzato da migliaia di organizzazioni e che oltre l’80% delle aziende Fortune 100 si affida ad esso.
In molte organizzazioni, Kafka è la spina dorsale dei loro sistemi, e l’ecosistema Kafka è in costante crescita.
Ma gestire un cluster Kafka affidabile può essere impegnativo: ha moltissime impostazioni sia a livello di broker che di topic, è distribuito e ovviamente vogliamo che sia altamente disponibile.
Il monitoraggio è cruciale: senza una corretta configurazione per la raccolta delle metriche, la costruzione di dashboard e infine la definizione di alert, il team operativo è cieco.
In questo articolo descriverò i problemi noti delle metriche di Kafka e proporrò una soluzione che, si spera, ne risolve la maggior parte — o forse anche tutti.
Hai importato una dashboard Grafana per Kafka e non mostra alcun dato? Troverai la risposta qui sotto.
Cos’è Kafka, esattamente?
Scommetto che se stai leggendo questo articolo, sai perfettamente cos’è Kafka e qual è il suo scopo. Ma ecco un breve riepilogo:
Apache Kafka è una piattaforma distribuita di event streaming. Il modo più semplice per pensarci: Kafka è un log durevole, di tipo append-only, che permette a molte applicazioni di scrivervi eventi — i producer — e a molte altre di rileggere quegli eventi — i consumer — in tempo reale e con throughput molto elevato.
Gli eventi vivono nei topic, che sono suddivisi in partizioni e replicati su più broker, i server che compongono un cluster Kafka. Questo offre scalabilità orizzontale e tolleranza ai guasti: se un broker muore, un’altra replica subentra e i consumer continuano a leggere senza perdere un colpo.
Oggi Kafka è al centro di molti sistemi mission-critical: pipeline di pagamento, rilevamento di frodi, comunicazione tra microservizi, change data capture dai database, aggregazione di log, telemetria IoT. Quando funziona bene, nessuno se ne accorge. Quando non funziona, è un disastro.
Il sistema di metriche all’interno di Kafka — la radice del problema
Sapevi che i broker Kafka espongono le metriche attraverso due diversi sistemi di metriche? Io no.
Le metriche di Kafka sono gestite da due librerie di metriche separate che girano nella stessa JVM.
La più vecchia è Yammer Metrics. È in Kafka fin dagli albori, e molte metriche fondamentali del broker — per esempio BytesInPerSec, MessagesInPerSec e UnderReplicatedPartitions — sono ancora gestite da essa.
La seconda è Kafka Metrics, org.apache.kafka.common.metrics, nota anche come SPI — Service Provider Interface. È stata introdotta quando sono stati creati i client Java. È utilizzata anche da strumenti dell’ecosistema come Kafka Streams e Kafka Connect.
Questa non è solo una curiosità. La documentazione ufficiale sul monitoraggio di Apache Kafka afferma che Kafka utilizza Yammer Metrics per le metriche server, mentre i client Java utilizzano Kafka Metrics. Entrambi espongono le metriche tramite JMX e possono essere configurati con stats reporter collegabili.
Questi due sistemi esistono per ragioni storiche. A un certo punto, tutte le nuove metriche sono state create come metriche SPI, ma non c’era alcun piano per migrare le metriche Yammer verso SPI.
Ecco le principali differenze:
| Area | Yammer Metrics MBeans | Kafka Metrics MBeans |
|---|---|---|
| Uso principale in Kafka | Metriche classiche di broker/server/controller | Client Java e moduli broker/controller più recenti/comuni |
| Configurazione del reporter | kafka.metrics.reporters | metric.reporters |
| Interfaccia del reporter | kafka.metrics.KafkaMetricsReporter | org.apache.kafka.common.metrics.MetricsReporter |
| Esposizione JMX di default | Yammer JMX reporter | org.apache.kafka.common.metrics.JmxReporter |
| Forma dell’MBean | Il nome della metrica è solitamente parte dell’ObjectName, come name=... | L’ObjectName è solitamente domain + type + tag; i nomi delle metriche sono solitamente attributi |
| Attributi | Attributi Yammer generici come Value, Count, MeanRate, OneMinuteRate, percentili | Nomi delle metriche Kafka come attributi, ad esempio byte-rate, throttle-time, connection-count, *-rate, *-total |
| Stile di esempio | kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec,topic=my-topic | kafka.server:type=Produce,user=alice,client-id=app1 con attributi come byte-rate, throttle-time |
Configurazione delle metriche di Kafka — il vecchio modo
Il modo tradizionale per monitorare Kafka è esportare le metriche da JMX con Prometheus JMX Exporter. È una libreria che gira come Java agent e viene configurata con un file di regole e un numero di porta.
La porta viene usata come endpoint Prometheus, con /metrics aggiunto in coda.
E il file di regole? È un enorme file YAML, con tonnellate di espressioni regolari. Di solito, nessuno ne comprende fino in fondo i dettagli e lo usa e basta, sperando che chiunque lo abbia scritto sapesse cosa stava facendo.
Quindi devi caricare JMX Exporter su tutti i broker, eventualmente creare o modificare il file di configurazione con le regole — buona fortuna con questo — e riavviare i broker. Se tutto va liscio, puoi fare il curl dell’endpoint delle metriche e vedere le metriche. Bene!
Poi raccogli queste metriche in Prometheus, scarichi qualche dashboard Kafka in Grafana e… nella maggior parte dei casi, vedi “No Data”. Perché? Perché non esiste un unico standard per le regole, quindi l’unica opzione è modificare la dashboard o provare a trovarne un’altra.
Ma c’è di più: ognuno di questi sistemi di metriche può essere configurato con una classe personalizzata, o plugin. Guarda la tabella qui sopra — sì, ci sono due impostazioni. Una con il prefisso kafka, l’altra senza. Una con metric al singolare, l’altra con metrics al plurale.
Eh già.
Ehi, siamo nel 2026, Kafka può usare OpenTelemetry?
La risposta breve è: non direttamente. Ma ci sono alcuni modi per insegnare a Kafka il protocollo OpenTelemetry.
Ci sono diversi modi per farlo:
- JMX Exporter più il receiver Prometheus nell’OpenTelemetry Collector — gli stessi problemi di mappatura JMX descritti sopra.
- JMX receiver dell’OpenTelemetry Collector — ancora basato su JMX, richiede di esporre JMX, e il componente è ora contrassegnato come deprecato, con la raccomandazione di usare invece un programma Java JMX Gatherer standalone.
- OpenTelemetry Java agent — una buona opzione. Può raccogliere le metriche dei broker Kafka attraverso il modulo JMX Metric Insight, e la demo di OpenTelemetry usa questo approccio per Kafka. Ma se vuoi un set personalizzato di metriche JMX, finisci comunque con un altro file di mappatura delle metriche.
La soluzione
E se avessimo qualcosa che affronta tutti i problemi descritti sopra?
Come accennato, le impostazioni metric.reporters e kafka.metrics.reporters sono semplicemente nomi di classi. Le classi devono implementare rispettivamente le interfacce org.apache.kafka.common.metrics.MetricsReporter e kafka.metrics.KafkaMetricsReporter.
Così ci è venuta l’idea: una libreria con le seguenti caratteristiche.
OTLP nativo, nessun passaggio per JMX
La maggior parte degli stack di osservabilità di Kafka aggancia jmx_exporter, o qualcosa di simile, come agent della JVM, poi fa lo scrape degli MBean su un endpoint HTTP, poi invia a un collector.
Questo plugin vive all’interno del processo Kafka e parla OTLP direttamente con il collector — un processo in meno, una superficie di configurazione in meno e nessun file YAML di regole JMX da mantenere.
Un solo plugin, entrambi i registry di Kafka
I broker Kafka espongono le metriche attraverso due sistemi paralleli: la SPI di Kafka, configurata con metric.reporters, e il registry legacy Yammer/Coda Hale.
Diversi segnali interni del broker — UnderReplicatedPartitions, OfflinePartitionsCount, ActiveControllerCount e i BrokerTopicMetrics per ogni topic — si registrano solo con Yammer.
OtlpMetricReporter si collega a entrambi con un’unica configurazione. Lo stesso JAR gira immutato sui client, dove il lato Yammer si auto-disabilita.
Fail-safe per progettazione — Kafka non viene mai bloccato
Le callback delle metriche come metricChange e metricRemoval toccano solo una ConcurrentHashMap in memoria. Tutto l’I/O avviene su un thread daemon scheduler.
Se il collector è irraggiungibile, la chiamata di export va in timeout, il batch viene scartato e il tick successivo riparte da zero. Nessuna coda di retry, nessuna memoria illimitata, nessun impatto sulla latenza di produce/fetch di Kafka.
Il contesto del broker diventa label Prometheus di prima classe
Kafka invoca MetricsReporter.contextChange(MetricsContext) con cluster id, node/broker id e versione di Kafka.
Il plugin cattura questi valori e li allega come resource attribute OTLP. Compaiono come label — kafka_cluster_id, kafka_node_id o kafka_broker_id — su ogni serie, quindi by(kafka_cluster_id, kafka_node_id) funziona in PromQL senza alcun cablaggio aggiuntivo.
Signore e signori, ecco a voi monedula-metrics-reporter
monedula-metrics-reporter è una libreria open source che soddisfa questi requisiti — e altro ancora.
Esporta le metriche di Kafka direttamente tramite OTLP usando gRPC o HTTP, supporta Kafka 3.x e 4.x su Java 17+ e può anche emettere metriche di runtime della JVM sulla stessa pipeline.
Include inoltre funzionalità pratiche di produzione come:
- allow-listing delle metriche,
- resource attribute personalizzati,
- configurazione di TLS e mTLS,
- compressione,
- metriche di self-monitoring del reporter,
- e supporto sia per broker che per client.
Il reporter emette anche le proprie metriche di salute, per esempio:
monedula_reporter_export_success_total,monedula_reporter_export_failure_total,monedula_reporter_export_duration_ms.
Quindi se la pipeline del collector si rompe, non ottieni solo silenzio. Ottieni segnali del fatto che il reporter stesso non riesce a esportare.
Il progetto include anche una quickstart facile da usare che dimostra il flusso completo con Kafka, l’OpenTelemetry Collector, Prometheus e Grafana. E poiché le dashboard fanno parte del problema, include un set curato di dashboard Grafana pronte all’uso che corrispondono alle metriche prodotte dal plugin.
Puoi trovarlo su GitHub, compilarlo localmente e testarlo con la quickstart. Gli artefatti precompilati arriveranno presto.
Se trovi un bug o hai un suggerimento per migliorarlo, sentiti libero di creare una issue su GitHub.
Riepilogo
Il monitoraggio di Kafka è più difficile di quanto dovrebbe essere perché Kafka espone le metriche attraverso due diversi sistemi di metriche, la maggior parte delle configurazioni di produzione si affida ancora a JMX e ogni mappatura da JMX a Prometheus crea un altro livello di compatibilità tra il broker, Prometheus e le dashboard Grafana.
monedula-metrics-reporter adotta un approccio diverso: gira come reporter di metriche di Kafka, esporta le metriche in modo nativo tramite OTLP, gestisce entrambi i registry di metriche di Kafka e include dashboard che corrispondono alle metriche emesse.
Quindi, le metriche di Kafka devono per forza essere così difficili?
Si spera non più.