---
title: "Metryki klientów Kafki przez OTLP — kolejny element układanki"
date: 2026-07-07T00:00:00.000Z
author: "grzegorz"
excerpt: "KIP-714 pozwala klientom Kafki wysyłać własne metryki do brokerów przez OTLP. monedula-metrics-reporter przekazuje teraz również te metryki, obok metryk broker SPI i Yammer."
---
W [poprzednim artykule](/blog/kafka-metrics-opentelemetry-otlp-monedula-metrics-reporter/) pisałem o metrykach brokerów Kafki i o tym, dlaczego ich zbieranie jest trudniejsze, niż powinno być.

W skrócie: Kafka nie ma jednego systemu metryk.

Ma nowsze Kafka Metrics SPI, konfigurowane przez `metric.reporters`, oraz starszy rejestr Yammer/Coda Hale, konfigurowany przez `kafka.metrics.reporters`. Część ważnych metryk brokera znajduje się w jednym systemie, część w drugim, a większość rzeczywistych konfiguracji monitoringu wciąż opiera się na JMX, wyrażeniach regularnych, mapowaniach Prometheusa i dashboardach, które mogą — ale nie muszą — odpowiadać eksportowanym nazwom.

To był powód powstania `monedula-metrics-reporter`: wtyczki Kafki, która eksportuje metryki bezpośrednio przez OTLP do OpenTelemetry Collector i obsługuje oba rejestry metryk Kafki z poziomu jednej konfiguracji.

Ale wciąż brakowało jednego elementu.

Metryki brokera mówią nam wiele o klastrze, ale nie wyjaśniają w pełni, co dzieje się wewnątrz aplikacji klienckich.

Broker może nam powiedzieć, że żądania Produce są wolne. Może nam powiedzieć, że żądania Fetch są wolne. Może nam powiedzieć o kolejkach żądań, procesorach sieciowych, niedostatecznie zreplikowanych partycjach, nieudanych żądaniach i wielu innych rzeczach.

Ale czasem prawdziwe pytanie brzmi nie tylko:

> Co dzieje się na brokerze?

Ale również:

> Co dzieje się wewnątrz producenta lub konsumenta?

Czy producent efektywnie grupuje rekordy w partie?
Czy jest dławiony (throttled)?
Czy konsument regularnie odpytuje (poll)?
Czy spędza czas na rebalansach?
Czy jedna aplikacja zachowuje się inaczej niż inna?

Tradycyjnie odpowiedź na te pytania oznaczała instrumentowanie każdej aplikacji klienckiej osobno. W Javie często znów oznaczało to JMX. W innych językach zależało to od biblioteki klienta, frameworka i tego, jaką konfigurację obserwowalności miał dany zespół.

A w większych organizacjach staje się to bardzo znanym problemem: zespół Kafki jest właścicielem klastra, ale aplikacje klienckie należą do wielu różnych zespołów. Kiedy więc coś idzie nie tak, operator klastra często nie ma potrzebnych metryk po stronie klienta, a ich zdobycie wymaga koordynacji, zmian w kodzie, ponownych wdrożeń lub przynajmniej restartów.

To dokładnie ten problem, który stara się rozwiązać [KIP-714](https://cwiki.apache.org/confluence/display/KAFKA/KIP-714%3A+Client+metrics+and+observability).

## Idea stojąca za KIP-714

KIP-714 dodaje sterowany przez broker sposób zbierania metryk od klientów Kafki.

Zamiast konfigurowania własnego eksportera metryk przez każdy zespół aplikacyjny, klaster Kafki może definiować subskrypcje metryk klientów. Subskrypcja określa, które metryki klientów powinny być zbierane i jak często klienci powinni je wysyłać.

Klienci wysyłają następnie swoje metryki do brokerów, korzystając z protokołu Kafki. Sam ładunek (payload) jest w formacie OTLP, więc wtyczka po stronie brokera może przekazać go do OpenTelemetry Collector, bazy danych szeregów czasowych lub dowolnego innego backendu obserwowalności.

Ważny jest kierunek sterowania.

To operator klastra decyduje, co zbierać.

Klienci obsługujący KIP-714 mogą otrzymać subskrypcję i wysyłać żądane metryki. Aplikacja nie musi udostępniać JMX. Nie potrzebuje eksportera typu sidecar. Nie potrzebuje własnego endpointu Prometheusa.

Wciąż obowiązują dwa warunki:

1. Broker musi mieć skonfigurowaną wtyczkę telemetrii klienta.
2. Musi istnieć co najmniej jedna subskrypcja metryk klientów.

Bez subskrypcji klienci mogą obsługiwać protokół, ale nie będą wysyłać metryk.

To dobry projekt. Metryki klientów nie są zbierane przypadkowo. Operator musi jawnie włączyć ich zbieranie po stronie klastra.

## Jeden ważny szczegół: nie każdy klient wysyła te same metryki

KIP-714 tworzy wspólny mechanizm zbierania metryk klientów, ale nie sprawia w magiczny sposób, że każdy klient Kafki udostępnia ten sam zestaw metryk.

Metryki, które otrzymujesz, zależą od biblioteki klienta.

Klient Java wysyła obecnie najbogatszy zestaw metryk. To nie jest zaskoczenie: klient Java to implementacja referencyjna, ma bardzo dojrzały wewnętrzny rejestr metryk, a wiele metryk Kafki zaprojektowano najpierw właśnie tam.

Inni klienci mogą udostępniać mniejszy zestaw. Klienci oparci na librdkafka, takie jak klienci używane w Pythonie, Go, .NET i wrapperach dla Node, także mogą uczestniczyć w KIP-714, ale dostępne metryki niekoniecznie są identyczne z tym, co wysyła klient Java.

Model myślowy powinien więc brzmieć:

> KIP-714 standaryzuje sposób, w jaki metryki klientów są zamawiane i transportowane.
> Rzeczywisty zestaw metryk wciąż zależy od implementacji klienta.

To ma znaczenie przy budowaniu dashboardów.

Niektóre panele mogą opierać się na wspólnych metrykach i powinny działać dla różnych bibliotek klienckich. Inne panele mają sens tylko wtedy, gdy klient faktycznie wysyła bogatszy zestaw metryk. W praktyce to klient Java daje dziś najbardziej kompletny obraz obserwowalności.

## Dlaczego dodać to do monedula-metrics-reporter?

Na początku `monedula-metrics-reporter` dotyczył metryk brokera.

Obsługiwał rejestr Kafka SPI.
Obsługiwał rejestr Yammer.
Eksportował oba przez OTLP.
Dodawał tożsamość brokera jako atrybuty zasobu (resource attributes).
Był dostarczany z dashboardami Grafany dopasowanymi do emitowanych metryk.

Ale skoro istnieje KIP-714, pojawia się bardzo naturalny kolejny krok:

> Skoro wtyczka i tak działa wewnątrz brokera i już eksportuje OTLP do collectora, powinna obsługiwać także metryki wysyłane przez klientów.

W przeciwnym razie monitoring Kafki wciąż byłby podzielony.

Miałbyś jedną ścieżkę dla metryk broker SPI, drugą dla metryk Yammer i jeszcze inną wtyczkę lub komponent dla telemetrii klientów z KIP-714.

To by działało, ale przekreślałoby całą ideę uproszczenia stosu metryk Kafki.

Dlatego nowa wersja `monedula-metrics-reporter` obsługuje teraz trzy źródła metryk:

1. Kafka Metrics SPI
2. Metryki brokera Yammer / Coda Hale
3. Telemetrię wysyłaną przez klientów z KIP-714

Cel jest prosty: jedna wtyczka, jeden potok collectora, jeden zestaw dashboardów.

Metryki klientów są przekazywane tą samą ścieżką OpenTelemetry co metryki brokera. Mogą nieść te same etykiety brokera, takie jak `kafka_cluster_id` i `kafka_node_id`, a także mogą być wzbogacone o `client_id`, tak aby metryki z różnych aplikacji nie zlewały się w jeden anonimowy strumień.

Ten ostatni punkt jest bardzo ważny.

Jeśli dwaj producenci wysyłają metrykę o tej samej nazwie, musimy wiedzieć, który producent jest który. Domyślnie reporter dodaje identyfikator klienta jako etykietę. Bardziej wrażliwe lub wysokokardynalne etykiety, takie jak identyfikator instancji klienta, principal czy adres klienta, są opcjonalne (opt-in).

## Jak to działa

Część po stronie brokera jest zaimplementowana przez interfejs `ClientTelemetry` w Kafce.

Kiedy klient obsługujący KIP-714 wysyła telemetrię do brokera, wtyczka odbiera ładunek OTLP. Wątek obsługi żądań (request-handler) wykonuje tylko minimalną pracę: kopiuje ładunek do ograniczonej kolejki w pamięci. Następnie wątek daemona odczytuje z tej kolejki, konwertuje ładunek na dane metryk OpenTelemetry SDK, wzbogaca je o etykiety i eksportuje przy użyciu dedykowanego eksportera metryk.

To ta sama zasada projektowa, co w reszcie reportera:

> Kafka nigdy nie może być blokowana przez potok obserwowalności.

Jeśli collector jest niedostępny, wolny lub źle skonfigurowany, Kafka powinna dalej obsługiwać ruch. Partię telemetrii można porzucić. Opóźnienie Kafki nie powinno zależeć od backendu monitoringu.

Odbiornik telemetrii klientów ma również własne metryki samomonitorowania:

```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
````

Jeśli więc telemetria klientów przestanie napływać, jest na co spojrzeć, zamiast zgadywać.

## Instalacja

Artefakt jest opublikowany w Maven Central, więc nie ma potrzeby budowania go ręcznie.

Dla wersji `0.10.0` pobierz plik JAR z 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
```

Następnie skopiuj go do classpath Kafki:

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

Potem skonfiguruj broker:

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

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

Włącza to reporter dla metryk Kafka SPI, metryk brokera Yammer oraz telemetrii klientów.

Telemetria klientów jest domyślnie włączona na brokerach:

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

Możesz ją jawnie wyłączyć:

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

Po wyłączeniu broker nie będzie ogłaszał klientom możliwości telemetrii.

## Konfiguracja collectora

Minimalna konfiguracja OpenTelemetry Collector może odbierać OTLP z reportera i udostępniać metryki dla Prometheusa:

```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]
```

Ustawienie `resource_to_telemetry_conversion` jest ważne przy korzystaniu z Prometheusa. Promuje ono atrybuty zasobu OpenTelemetry do etykiet Prometheusa.

Bez niego etykiety takie jak `kafka_cluster_id`, `kafka_node_id` i `client_id` mogą nie pojawić się tam, gdzie się ich spodziewasz.

Prometheus może następnie odpytywać collector:

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

## Najważniejsza część: subskrypcje metryk klientów

Zainstalowanie wtyczki nie wystarczy.

To ta część, którą przy KIP-714 łatwo przeoczyć.

Klienci wysyłają metryki tylko wtedy, gdy na klastrze skonfigurowana jest subskrypcja metryk klientów.

Na przykład:

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

Tworzy to lub aktualizuje subskrypcję o nazwie `all-clients`, żąda wszystkich dostępnych metryk klientów i ustawia interwał wysyłania na 5 sekund.

W zastosowaniach produkcyjnych zbieranie wszystkiego może być zbyt dużym obciążeniem. Można również subskrybować tylko wybrane prefiksy metryk.

Na przykład można zacząć od standardowych metryk klienta Kafki:

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

Dokładna strategia subskrypcji zależy od tego, co chcesz obserwować i jak duży wolumen metryk jesteś w stanie zaakceptować.

Istotne jest to, że subskrypcja żyje po stronie brokera. Dzięki temu operator Kafki może decydować, co powinno być zbierane, bez proszenia każdego zespołu aplikacyjnego o zmianę konfiguracji monitoringu.

## A co z konfiguracją klienta?

Dla klientów obsługujących KIP-714 wysyłanie metryk jest zwykle włączone domyślnie.

Mimo to możesz to zaznaczyć jawnie:

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

Dla klientów Java jest to część konfiguracji klienta Kafki.

Dla klientów opartych na librdkafka, takich jak `confluent-kafka-python`, obowiązuje ta sama zasada. Na przykład:

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

A dla konsumenta:

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

Warto świadomie ustawić `client.id`.

Reporter dodaje go domyślnie do przekazywanych metryk klienta, więc dashboardy mogą rozdzielać metryki według aplikacji. Bez sensownego identyfikatora klienta wciąż otrzymasz metryki, ale znacznie trudniej będzie ich używać podczas rozwiązywania problemów.

## Opcje wzbogacania

Domyślnie przekazywane metryki klienta są wzbogacane o tożsamość brokera i identyfikator klienta:

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

Oznacza to, że metryki klienta można grupować według klastra, brokera i aplikacji.

Istnieją też opcjonalne wzbogacenia:

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

Identyfikator instancji klienta jest przydatny, gdy chcesz rozróżnić poszczególne działające instancje klienta, ale ma wysoką kardynalność.

Tożsamość klienta dodaje principal i adres klienta. Może to być bardzo przydatne w kontrolowanych środowiskach, ale może również zawierać informacje wrażliwe, dlatego jest domyślnie wyłączona.

Krótko mówiąc: zacznij od etykiet brokera i identyfikatora klienta. Resztę włączaj tylko wtedy, gdy naprawdę tego potrzebujesz.

## Szybki start

Repozytorium zawiera stack szybkiego startu z Kafką, OpenTelemetry Collector, Prometheusem i Grafaną.

Uruchom szybki start:

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

Serwis demonstracyjny tworzy subskrypcję metryk klientów KIP-714 i uruchamia ruch producenta oraz konsumenta. Po postawieniu stacku zarówno dashboardy brokera, jak i dashboardy klientów powinny zacząć otrzymywać dane.

Grafana jest dostępna pod adresem:

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

Prometheus jest dostępny pod adresem:

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

Szybki start tworzy subskrypcję poleceniem:

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

Jest to celowo proste: zbierz wszystko, wysyłaj co 5 sekund i szybko ożyw dashboardy.

W rzeczywistych środowiskach zwykle zacząłbym ostrożniej. Najpierw zebrałbym standardowe metryki, sprawdziłbym wolumen, a potem w razie potrzeby dodawał kolejne metryki.

## Klienci Java a inni klienci

Ciekawą cechą KIP-714 jest to, że tworzy on wspólny mechanizm, ale nie każda biblioteka klienta udostępnia tę samą głębię metryk.

Klient Java wysyła najbogatszy zestaw metryk. Może wysyłać wiele metryk ze swojego wewnętrznego rejestru, w tym bogatsze szczegóły producenta i konsumenta: grupowanie w partie, wykorzystanie buforów, czasy żądań, podziały na poziomie tematów, opóźnienie (lag) i wyprzedzenie (lead) konsumenta oraz inne sygnały specyficzne dla klienta Java.

Inne biblioteki klienckie mogą wysyłać mniejszy zestaw.

Nie oznacza to, że KIP-714 jest przydatny tylko dla klientów Java. Wciąż bardzo użyteczne jest posiadanie wspólnej, sterowanej przez broker ścieżki zbierania dla wszystkich klientów, którzy go obsługują. Ale patrząc na dashboardy, warto pamiętać, że brakujące panele nie zawsze oznaczają, że coś jest zepsute.

Czasem metryka po prostu nie istnieje w danej bibliotece klienta.

Właśnie dlatego nowe dashboardy Grafany są podzielone na dwie części:

1. Panele standardowe
2. Panele rozszerzone

Panele standardowe powinny działać dla każdego klienta zgodnego z KIP-714, który udostępnia odpowiednie wspólne metryki.

Panele rozszerzone są przydatne głównie dla klienta Java, ponieważ to on obecnie dostarcza najbogatszy zestaw metryk.

Ten podział jest celowy. Nie chcę dashboardu, który wygląda na zepsuty tylko dlatego, że klient inny niż Java nie udostępnia metryk specyficznych dla Javy. Lepiej uczynić tę granicę widoczną.

## Nowe dashboardy

Nowa wersja dodaje dwa dashboardy skoncentrowane na kliencie:

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

Dashboard producenta skupia się na widoku produkcji rekordów od strony klienta: opóźnieniu żądań, dławieniu (throttling), kolejkowaniu, grupowaniu w partie, błędach i przepustowości.

Dashboard konsumenta skupia się na widoku konsumpcji rekordów od strony klienta: opóźnieniu pobierania (fetch), tempie commitów, zachowaniu podczas pollowania, sygnałach związanych z rebalansem, zmianach przydziału (assignment) oraz opóźnieniu/wyprzedzeniu konsumenta tam, gdzie są dostępne.

Oba dashboardy zawierają filtry według klastra i identyfikatora klienta. Tam, gdzie pozwala na to zestaw metryk, obejmują również szczegółowe wglądy (drill-down) na poziomie tematu lub grupy.

<figure>
  <img src="/blog/monedula-metrics-reporter-kip-714/producer-dashboard.png" alt="Dashboard producenta - strona klienta." />
  <figcaption>Dashboard producenta - strona klienta</figcaption>
</figure>

<figure>
  <img src="/blog/monedula-metrics-reporter-kip-714/consumer-dashboard.png" alt="Dashboard konsumenta - strona klienta." />
  <figcaption>Dashboard konsumenta - strona klienta</figcaption>
</figure>

Jest jedna rzecz, którą naprawdę lubię w tej konfiguracji: ten sam folder Grafany może teraz pokazać obie strony tej historii.

Dashboardy brokera odpowiadają na pytanie:

> Czy klaster jest zdrowy?

Dashboardy klientów odpowiadają na pytanie:

> Jak aplikacje doświadczają klastra?

A ponieważ oba pochodzą z tego samego potoku OTLP, ze spójnymi etykietami, ich skorelowanie staje się znacznie łatwiejsze.

## Podsumowanie

KIP-714 to bardzo ważny krok dla obserwowalności Kafki.

Zamienia metryki klientów z czegoś, co każdy zespół aplikacyjny musi udostępniać niezależnie, w coś, o co klaster Kafki może poprosić centralnie.

`monedula-metrics-reporter` obsługuje teraz ten model.

Wciąż eksportuje metryki brokera z obu rejestrów metryk Kafki. Ale teraz odbiera również telemetrię OTLP wysyłaną przez klientów zgodnych z KIP-714 i przekazuje ją do tego samego OpenTelemetry Collector.

Wtyczka obejmuje więc teraz trzy źródła:

* Metryki Kafka SPI
* Metryki brokera Yammer
* Telemetrię klientów z KIP-714

Rezultatem jest prostsza architektura monitoringu Kafki: jedna wtyczka na brokerach, jeden potok OTLP i dashboardy obejmujące zachowanie zarówno po stronie brokera, jak i po stronie klienta.

Kod jest open source i [dostępny na GitHubie](https://github.com/monedula-dev/monedula-metrics-reporter)