---
title: "Metriche dei client Kafka via OTLP — un altro pezzo del puzzle"
date: 2026-07-07T00:00:00.000Z
author: "grzegorz"
excerpt: "KIP-714 permette ai client Kafka di inviare le proprie metriche ai broker via OTLP. monedula-metrics-reporter ora inoltra anche queste metriche, accanto a quelle del broker SPI e a quelle Yammer."
---
Nell'[articolo precedente](/blog/kafka-metrics-opentelemetry-otlp-monedula-metrics-reporter/) ho parlato delle metriche del broker Kafka e del perché raccoglierle sia più difficile di quanto dovrebbe essere.

In breve: Kafka non ha un unico sistema di metriche.

Ha la più recente Kafka Metrics SPI, configurata con `metric.reporters`, e il più vecchio registry Yammer/Coda Hale, configurato con `kafka.metrics.reporters`. Alcune metriche importanti del broker vivono in un sistema, altre nell'altro, e la maggior parte dei setup di monitoraggio reali passa ancora attraverso JMX, espressioni regolari, mapping Prometheus e dashboard che possono corrispondere oppure no ai nomi esportati.

Questo è stato il motivo per cui è nato `monedula-metrics-reporter`: un plugin Kafka che esporta le metriche direttamente via OTLP verso un OpenTelemetry Collector e gestisce entrambi i registry di metriche di Kafka con un'unica configurazione.

Ma mancava ancora un pezzo.

Le metriche del broker ci dicono molto sul cluster, ma non spiegano del tutto cosa sta succedendo dentro le applicazioni client.

Un broker può dirci che le richieste di Produce sono lente. Può dirci che le richieste di Fetch sono lente. Può dirci delle code delle richieste, dei network processor, delle partizioni under-replicated, delle richieste fallite e di molte altre cose.

Ma a volte la vera domanda non è solo:

> Cosa sta succedendo sul broker?

È anche:

> Cosa sta succedendo dentro il producer o il consumer?

Il producer sta facendo batching in modo efficiente?
È throttled?
Il consumer fa poll con regolarità?
Sta passando tempo nei rebalance?
Un'applicazione si comporta in modo diverso da un'altra?

Tradizionalmente, rispondere a queste domande significava strumentare ogni applicazione client separatamente. In Java, spesso significava di nuovo JMX. In altri linguaggi dipendeva dalla libreria client, dal framework e da qualunque setup di observability avesse il team.

E nelle organizzazioni più grandi questo diventa un problema molto familiare: il team Kafka possiede il cluster, ma le applicazioni client appartengono a molti team diversi. Quindi, quando qualcosa va storto, chi gestisce il cluster spesso non ha le metriche lato client di cui ha bisogno, e ottenerle richiede coordinamento, modifiche al codice, redeploy o quantomeno restart.

È esattamente questo il problema che [KIP-714](https://cwiki.apache.org/confluence/display/KAFKA/KIP-714%3A+Client+metrics+and+observability) cerca di risolvere.

## L'idea dietro KIP-714

KIP-714 aggiunge un modo, guidato dal broker, per raccogliere le metriche dai client Kafka.

Invece che ogni team applicativo configuri il proprio esportatore di metriche, il cluster Kafka può definire delle client metric subscription. Una subscription indica quali metriche del client raccogliere e con quale frequenza i client debbano inviarle.

I client inviano poi le loro metriche ai broker usando il protocollo Kafka. Il payload stesso è OTLP, così il plugin lato broker può inoltrarlo a un OpenTelemetry Collector, a un database time-series o a qualsiasi altro backend di observability.

La parte importante è la direzione del controllo.

È chi gestisce il cluster a decidere cosa raccogliere.

I client che supportano KIP-714 possono ricevere la subscription e inviare le metriche richieste. L'applicazione non ha bisogno di esporre JMX. Non ha bisogno di un esportatore sidecar. Non ha bisogno di un endpoint Prometheus personalizzato.

Restano comunque due condizioni:

1. Il broker deve avere un plugin di client telemetry configurato.
2. Deve esistere almeno una client metrics subscription.

Senza una subscription, i client possono anche supportare il protocollo, ma non invieranno metriche.

È un buon design. Le metriche dei client non vengono raccolte per caso. Chi gestisce il cluster deve abilitare esplicitamente la raccolta dal lato cluster.

## Un dettaglio importante: non tutti i client inviano le stesse metriche

KIP-714 crea un meccanismo comune per raccogliere le metriche dei client, ma non fa magicamente sì che ogni client Kafka esponga lo stesso set di metriche.

Le metriche che ottieni dipendono dalla libreria client.

Il client Java attualmente invia il set di metriche più ricco. Non sorprende: il client Java è l'implementazione di riferimento, ha un registry interno di metriche molto maturo e molte metriche Kafka sono state progettate lì per prime.

Altri client possono esporre un set più ridotto. I client basati su librdkafka, come quelli usati dai wrapper per Python, Go, .NET e Node, possono comunque partecipare a KIP-714, ma le metriche disponibili non sono necessariamente identiche a quelle inviate dal client Java.

Quindi il modello mentale dovrebbe essere:

> KIP-714 standardizza il modo in cui le metriche dei client vengono richieste e trasportate.
> Il set effettivo di metriche dipende ancora dall'implementazione del client.

Questo conta quando si costruiscono dashboard.

Alcuni pannelli possono basarsi su metriche comuni e dovrebbero funzionare con librerie client diverse. Altri pannelli hanno senso solo quando il client invia effettivamente il set di metriche più ricco. In pratica, oggi il client Java offre la storia di observability più completa.

## Perché aggiungere tutto questo a monedula-metrics-reporter?

All'inizio `monedula-metrics-reporter` riguardava le metriche del broker.

Gestiva il registry Kafka SPI.
Gestiva il registry Yammer.
Esportava entrambi via OTLP.
Aggiungeva l'identità del broker come resource attribute.
Veniva fornito con dashboard Grafana corrispondenti alle metriche emesse.

Ma una volta che esiste KIP-714, c'è un passo successivo molto naturale:

> Se il plugin gira già dentro il broker ed esporta già OTLP verso il collector, dovrebbe gestire anche le metriche inviate dai client.

Altrimenti il monitoraggio di Kafka resterebbe frammentato.

Avresti un percorso per le metriche broker SPI, un altro per le metriche Yammer e un ulteriore plugin o componente per la client telemetry KIP-714.

Funzionerebbe, ma vanificherebbe l'intera idea di semplificare lo stack di metriche di Kafka.

Così la nuova versione di `monedula-metrics-reporter` ora gestisce tre fonti di metriche:

1. Kafka Metrics SPI
2. Metriche del broker Yammer / Coda Hale
3. Telemetria inviata dai client via KIP-714

L'obiettivo è semplice: un plugin, una pipeline del collector, un set di dashboard.

Le metriche dei client vengono inoltrate attraverso lo stesso percorso OpenTelemetry delle metriche del broker. Possono portare le stesse label del broker, come `kafka_cluster_id` e `kafka_node_id`, e possono anche essere arricchite con il `client_id`, così le metriche di applicazioni diverse non si fondono in un unico flusso anonimo.

Quest'ultimo punto è molto importante.

Se due producer inviano lo stesso nome di metrica, dobbiamo sapere quale producer è quale. Per default il reporter aggiunge il client id come label. Label più sensibili o ad alta cardinalità, come client instance id, principal o client address, sono opt-in.

## Come funziona

La parte lato broker è implementata tramite l'interfaccia `ClientTelemetry` di Kafka.

Quando un client compatibile con KIP-714 invia telemetria a un broker, il plugin riceve il payload OTLP. Il thread request-handler fa solo il lavoro minimo indispensabile: copia il payload su una coda in memoria limitata. Poi un daemon thread legge da quella coda, converte il payload in dati di metrica dell'OpenTelemetry SDK, li arricchisce con le label e li esporta usando un esportatore di metriche dedicato.

È lo stesso principio di design del resto del reporter:

> Kafka non deve mai essere bloccato dalla pipeline di observability.

Se il collector è non disponibile, lento o mal configurato, Kafka deve continuare a servire il traffico. Il batch di telemetria può essere scartato. La latenza di Kafka non deve dipendere dal backend di monitoraggio.

Anche il ricevitore di client telemetry ha le sue metriche di self-monitoring:

```text
monedula_reporter_clienttelemetry_received_total
monedula_reporter_clienttelemetry_forwarded_total
monedula_reporter_clienttelemetry_dropped_total
monedula_reporter_clienttelemetry_unsupported_metrics_dropped_total
monedula_reporter_clienttelemetry_queue_depth
````

Così, se la client telemetry smette di fluire, c'è qualcosa da guardare prima di tirare a indovinare.

## Installazione

L'artefatto è pubblicato su Maven Central, quindi non c'è bisogno di compilarlo manualmente.

Per la versione `0.10.0`, scarica il JAR da Maven Central:

```bash
curl -L \
  -o monedula-metrics-reporter-0.10.0.jar \
  https://repo1.maven.org/maven2/dev/monedula/monedula-metrics-reporter/0.10.0/monedula-metrics-reporter-0.10.0.jar
```

Poi copialo nel classpath di Kafka:

```bash
cp monedula-metrics-reporter-0.10.0.jar $KAFKA_HOME/libs/
```

Dopodiché, configura il broker:

```properties
metric.reporters=dev.monedula.metricsreporter.OtlpMetricReporter

otlp.metric.reporter.endpoint=http://otel-collector:4317
otlp.metric.reporter.transport=grpc
```

Questo abilita il reporter per le metriche Kafka SPI, le metriche del broker Yammer e la client telemetry.

La client telemetry è abilitata per default sui broker:

```properties
otlp.metric.reporter.client.telemetry.enabled=true
```

Puoi disabilitarla esplicitamente:

```properties
otlp.metric.reporter.client.telemetry.enabled=false
```

Quando è disabilitata, il broker non pubblicizzerà ai client la capacità di telemetria.

## Configurazione del collector

Una configurazione minima dell'OpenTelemetry Collector può ricevere OTLP dal reporter ed esporre le metriche per Prometheus:

```yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"
      http:
        endpoint: "0.0.0.0:4318"

exporters:
  prometheus:
    endpoint: "0.0.0.0:8889"
    resource_to_telemetry_conversion:
      enabled: true

service:
  pipelines:
    metrics:
      receivers: [otlp]
      exporters: [prometheus]
```

L'impostazione `resource_to_telemetry_conversion` è importante quando si usa Prometheus. Promuove i resource attribute di OpenTelemetry a label Prometheus.

Senza di essa, label come `kafka_cluster_id`, `kafka_node_id` e `client_id` potrebbero non comparire dove te le aspetti.

Prometheus può poi fare lo scrape del collector:

```yaml
scrape_configs:
  - job_name: otel-collector
    static_configs:
      - targets: ["otel-collector:8889"]
```

## La parte importante: le client metric subscription

Installare il plugin non basta.

È questa la parte facile da dimenticare con KIP-714.

I client inviano metriche solo quando sul cluster è configurata una client metrics subscription.

Per esempio:

```bash
kafka-client-metrics.sh \
  --bootstrap-server broker:9092 \
  --alter \
  --name all-clients \
  --metrics "*" \
  --interval 5000
```

Questo crea o aggiorna una subscription chiamata `all-clients`, richiede tutte le metriche client disponibili e imposta l'intervallo di invio a 5 secondi.

Per l'uso in produzione, raccogliere tutto potrebbe essere troppo. Puoi anche sottoscriverti solo a determinati prefissi di metriche.

Per esempio, puoi partire dalle metriche standard dei client Kafka:

```bash
kafka-client-metrics.sh \
  --bootstrap-server broker:9092 \
  --alter \
  --name standard-client-metrics \
  --metrics "org.apache.kafka." \
  --interval 10000
```

La strategia di subscription esatta dipende da cosa vuoi osservare e da quanto volume di metriche sei disposto a gestire.

La cosa importante è che la subscription risiede sul lato broker. Questo permette a chi gestisce Kafka di decidere cosa raccogliere senza chiedere a ogni team applicativo di modificare il proprio setup di monitoraggio.

## E la configurazione dei client?

Per i client che supportano KIP-714, l'invio delle metriche è di solito abilitato per default.

Puoi comunque renderlo esplicito:

```properties
enable.metrics.push=true
```

Per i client Java, questo fa parte della configurazione del client Kafka.

Per i client basati su librdkafka, come `confluent-kafka-python`, vale la stessa idea. Per esempio:

```python
Producer({
    "bootstrap.servers": "broker:9092",
    "client.id": "orders-producer",
    "enable.metrics.push": True,
})
```

E per un consumer:

```python
Consumer({
    "bootstrap.servers": "broker:9092",
    "group.id": "orders-consumer-group",
    "client.id": "orders-consumer",
    "enable.metrics.push": True,
})
```

Vale la pena impostare il `client.id` con cura.

Il reporter lo aggiunge per default alle metriche client inoltrate, così le dashboard possono separare le metriche per applicazione. Senza un client id significativo, otterrai comunque le metriche, ma saranno molto più difficili da usare durante il troubleshooting.

## Opzioni di arricchimento

Per default, le metriche client inoltrate vengono arricchite con l'identità del broker e il client id:

```properties
otlp.metric.reporter.client.telemetry.enrich.broker=true
otlp.metric.reporter.client.telemetry.enrich.client.id=true
```

Questo significa che le metriche dei client possono essere raggruppate per cluster, broker e applicazione.

Ci sono anche arricchimenti opzionali:

```properties
otlp.metric.reporter.client.telemetry.enrich.client.instance.id=true
otlp.metric.reporter.client.telemetry.enrich.client.identity=true
```

Il client instance id è utile quando vuoi distinguere le singole istanze client in esecuzione, ma è ad alta cardinalità.

Il client identity aggiunge principal e client address. Può essere molto utile in ambienti controllati, ma può anche contenere informazioni sensibili, quindi è disabilitato per default.

In breve: parti dalle label del broker e dal client id. Abilita il resto solo quando ne hai davvero bisogno.

## Quickstart

Il repository contiene uno stack quickstart con Kafka, l'OpenTelemetry Collector, Prometheus e Grafana.

Avvia il quickstart:

```bash
cd quickstart
docker compose up -d
```

Il servizio demo crea una client metrics subscription KIP-714 e avvia traffico di producer e consumer. Così, dopo che lo stack è attivo, sia le dashboard del broker sia quelle dei client dovrebbero iniziare a ricevere dati.

Grafana è disponibile su:

```text
http://localhost:3000
```

Prometheus è disponibile su:

```text
http://localhost:9090
```

Il quickstart crea la subscription con:

```bash
kafka-client-metrics.sh \
  --bootstrap-server kafka1:9092 \
  --alter \
  --name quickstart-clients \
  --metrics "*" \
  --interval 5000
```

È volutamente semplice: raccogliere tutto, inviare ogni 5 secondi e far prendere vita rapidamente alle dashboard.

Per gli ambienti reali, di solito partirei con più cautela. Prima raccogliere le metriche standard, validare il volume e poi aggiungere altre metriche se necessario.

## Client Java vs altri client

Una cosa interessante di KIP-714 è che crea un meccanismo comune, ma non tutte le librerie client espongono la stessa profondità di metriche.

Il client Java invia il set di metriche più ricco. Può inviare molte metriche dal suo registry interno, inclusi dettagli più ricchi di producer e consumer: batching, uso del buffer, timing delle richieste, breakdown a livello di topic, lag e lead del consumer e altri segnali specifici del client Java.

Altre librerie client possono inviare un set più ridotto.

Questo non significa che KIP-714 sia utile solo per i client Java. È comunque molto utile avere un percorso di raccolta comune, guidato dal broker, per tutti i client che lo supportano. Ma quando guardi le dashboard, dovresti ricordare che i pannelli mancanti non significano sempre che qualcosa è rotto.

A volte la metrica semplicemente non esiste in quella libreria client.

Ecco perché le nuove dashboard Grafana sono divise in due parti:

1. Pannelli standard
2. Pannelli estesi

I pannelli standard dovrebbero funzionare per ogni client conforme a KIP-714 che espone le relative metriche comuni.

I pannelli estesi sono utili soprattutto per il client Java, perché il client Java attualmente fornisce il set di metriche più ricco.

Questa divisione è intenzionale. Non voglio una dashboard che sembri rotta solo perché un client non-Java non espone metriche specifiche di Java. È meglio rendere visibile il confine.

## Nuove dashboard

La nuova versione aggiunge due dashboard focalizzate sui client:

* Kafka Producers (client)
* Kafka Consumers (client)

La dashboard del producer si concentra sulla vista lato client della produzione di record: latenza delle richieste, throttling, accodamento, batching, errori e throughput.

La dashboard del consumer si concentra sulla vista lato client del consumo di record: latenza di fetch, tasso di commit, comportamento del poll, segnali relativi ai rebalance, cambiamenti di assegnazione e, dove disponibili, lag/lead lato consumer.

Entrambe le dashboard includono filtri per cluster e client id. Dove il set di metriche lo permette, includono anche drill-down a livello di topic o group.

<figure>
  <img src="/blog/monedula-metrics-reporter-kip-714/producer-dashboard.png" alt="La dashboard del producer - lato client." />
  <figcaption>La dashboard del producer - lato client</figcaption>
</figure>

<figure>
  <img src="/blog/monedula-metrics-reporter-kip-714/consumer-dashboard.png" alt="La dashboard del consumer - lato client." />
  <figcaption>La dashboard del consumer - lato client</figcaption>
</figure>

C'è una cosa che mi piace davvero di questo setup: la stessa cartella Grafana ora può mostrare entrambi i lati della storia.

Le dashboard del broker rispondono a:

> Il cluster è in salute?

Le dashboard dei client rispondono a:

> Come vivono le applicazioni l'esperienza del cluster?

E poiché entrambe provengono dalla stessa pipeline OTLP, con label coerenti, diventa molto più facile correlarle.

## Riepilogo

KIP-714 è un passo molto importante per l'observability di Kafka.

Trasforma le metriche dei client da qualcosa che ogni team applicativo deve esporre in modo indipendente in qualcosa che il cluster Kafka può richiedere in modo centralizzato.

`monedula-metrics-reporter` ora supporta questo modello.

Esporta ancora le metriche del broker da entrambi i registry di metriche di Kafka. Ma ora riceve anche la telemetria OTLP inviata dai client KIP-714 e la inoltra allo stesso OpenTelemetry Collector.

Così il plugin ora copre tre fonti:

* Metriche Kafka SPI
* Metriche del broker Yammer
* Client telemetry KIP-714

Il risultato è un'architettura di monitoraggio di Kafka più semplice: un plugin sui broker, una pipeline OTLP e dashboard che coprono il comportamento sia lato broker sia lato client.

Il codice è open source ed è [disponibile su GitHub](https://github.com/monedula-dev/monedula-metrics-reporter)