Hoy en día, Apache Kafka es una de las piezas de software más utilizadas en TI. Está en todas partes, es un estándar de facto para el streaming de eventos y goza de amplia adopción en grandes empresas. El proyecto Apache Kafka afirma que Kafka es utilizado por miles de organizaciones y que confían en él más del 80 % de las empresas de la lista Fortune 100.

En muchas organizaciones, Kafka es la columna vertebral de sus sistemas, y el ecosistema de Kafka crece constantemente.

Pero operar un clúster de Kafka fiable puede ser todo un reto: tiene muchísimos ajustes tanto a nivel de broker como de topic, es distribuido y, obviamente, queremos que tenga alta disponibilidad.

La monitorización es crucial: sin una configuración adecuada para recopilar métricas, construir dashboards y, finalmente, definir alertas, el equipo de operaciones está ciego.

En este artículo describiré los problemas conocidos de las métricas de Kafka y propondré una solución que, con suerte, resuelve la mayoría de ellos, o quizá incluso todos.

¿Has importado un dashboard de Kafka en Grafana y no muestra ningún dato? Encontrarás la respuesta más abajo.

¿Qué es Kafka, en realidad?

Apuesto a que, si estás leyendo este artículo, sabes perfectamente qué es Kafka y cuál es su propósito. Pero aquí va un repaso rápido:

Apache Kafka es una plataforma distribuida de streaming de eventos. La forma más sencilla de pensar en ello: Kafka es un log duradero y de solo anexado (append-only) que permite que muchas aplicaciones escriban eventos en él (los producers) y que muchas otras lean esos eventos de vuelta (los consumers) en tiempo real, con un rendimiento muy alto.

Los eventos viven en topics, que se dividen en partitions y se replican entre múltiples brokers, los servidores que componen un clúster de Kafka. Eso te da escalabilidad horizontal y tolerancia a fallos: si un broker muere, otra réplica toma el relevo y los consumers siguen leyendo sin perder el ritmo.

Hoy, Kafka se sitúa en el corazón de muchos sistemas de misión crítica: canalizaciones de pagos, detección de fraude, comunicación entre microservicios, captura de cambios de datos (change data capture) desde bases de datos, agregación de logs, telemetría de IoT. Cuando funciona bien, nadie se da cuenta. Cuando no, es un desastre.

El sistema de métricas dentro de Kafka: la raíz del problema

¿Sabías que los brokers de Kafka exponen métricas a través de dos sistemas de métricas diferentes? Yo no.

Las métricas de Kafka las gestionan dos bibliotecas de métricas separadas que se ejecutan en la misma JVM.

La más antigua es Yammer Metrics. Lleva en Kafka desde los primeros días, y muchas métricas fundamentales del broker —por ejemplo BytesInPerSec, MessagesInPerSec y UnderReplicatedPartitions— siguen siendo gestionadas por ella.

La segunda es Kafka Metrics, org.apache.kafka.common.metrics, también conocida como la SPI (Service Provider Interface). Se introdujo cuando se crearon los clientes de Java. También la utilizan herramientas del ecosistema como Kafka Streams y Kafka Connect.

Esto no es solo una curiosidad. La documentación oficial de monitorización de Apache Kafka dice que Kafka usa Yammer Metrics para las métricas del servidor, mientras que los clientes de Java usan Kafka Metrics. Ambas exponen métricas a través de JMX y pueden configurarse con reporters de estadísticas conectables (pluggable).

Estos dos sistemas existen por razones históricas. En algún momento, todas las métricas nuevas se crearon como métricas de la SPI, pero no hubo ningún plan para migrar las métricas de Yammer a la SPI.

Estas son las principales diferencias:

ÁreaMBeans de Yammer MetricsMBeans de Kafka Metrics
Uso principal en KafkaMétricas clásicas de broker/server/controllerClientes de Java y módulos de broker/controller más nuevos/comunes
Configuración del reporterkafka.metrics.reportersmetric.reporters
Interfaz del reporterkafka.metrics.KafkaMetricsReporterorg.apache.kafka.common.metrics.MetricsReporter
Exposición JMX por defectoReporter JMX de Yammerorg.apache.kafka.common.metrics.JmxReporter
Forma del MBeanEl nombre de la métrica suele formar parte del ObjectName, como name=...El ObjectName suele ser dominio + tipo + tags; los nombres de métricas suelen ser atributos
AtributosAtributos genéricos de Yammer como Value, Count, MeanRate, OneMinuteRate, percentilesNombres de métricas de Kafka como atributos, tales como byte-rate, throttle-time, connection-count, *-rate, *-total
Estilo de ejemplokafka.server:type=BrokerTopicMetrics,name=BytesInPerSec,topic=my-topickafka.server:type=Produce,user=alice,client-id=app1 con atributos como byte-rate, throttle-time

Configuración de métricas de Kafka: la forma tradicional

La forma tradicional de monitorizar Kafka es exportar métricas desde JMX con Prometheus JMX Exporter. Es una biblioteca que se ejecuta como un agente de Java y se configura con un archivo de reglas y un número de puerto.

El puerto se usa como endpoint de Prometheus, con /metrics añadido al final.

¿Y el archivo de reglas? Es un archivo YAML enorme, con toneladas de expresiones regulares. Por lo general, nadie entiende del todo los detalles y simplemente lo usa, esperando que quien lo escribió supiera lo que estaba haciendo.

Así que tienes que subir JMX Exporter a todos los brokers, posiblemente crear o editar el archivo de configuración con reglas —buena suerte con esto— y reiniciar los brokers. Si todo va bien, puedes hacer curl al endpoint de métricas y ver las métricas. ¡Genial!

Luego haces scrape de esas métricas hacia Prometheus, descargas algunos dashboards de Kafka en Grafana y… en la mayoría de los casos, ves “No Data”. ¿Por qué? Porque no existe un único estándar para las reglas, así que la única opción es editar el dashboard o intentar encontrar otro.

Pero hay más: cada uno de estos sistemas de métricas puede configurarse con una clase personalizada, o plugin. Mira la tabla de arriba: sí, hay dos ajustes. Uno con el prefijo kafka, el otro sin él. Uno con metric en singular, el otro con metrics en plural.

Pues sí.

Oye, estamos en 2026, ¿puede Kafka usar OpenTelemetry?

La respuesta corta es: no directamente. Pero hay algunas formas de enseñarle a Kafka el protocolo de OpenTelemetry.

Hay varias maneras de hacerlo:

  • JMX Exporter más el receptor de Prometheus en el OpenTelemetry Collector: los mismos problemas de mapeo de JMX descritos arriba.
  • Receptor JMX del OpenTelemetry Collector: sigue basándose en JMX, requiere exponer JMX y el componente está ahora marcado como obsoleto (deprecated), con la recomendación de usar en su lugar un programa Java JMX Gatherer independiente.
  • Agente de Java de OpenTelemetry: una buena opción. Puede recopilar métricas del broker de Kafka a través del módulo JMX Metric Insight, y la demo de OpenTelemetry usa este enfoque para Kafka. Pero si quieres un conjunto personalizado de métricas JMX, acabas de nuevo con otro archivo de mapeo de métricas.

La solución

¿Y si tuviéramos algo que abordara todos los problemas descritos arriba?

Como hemos mencionado, los ajustes metric.reporters y kafka.metrics.reporters son solo nombres de clases. Las clases tienen que implementar las interfaces org.apache.kafka.common.metrics.MetricsReporter y kafka.metrics.KafkaMetricsReporter, respectivamente.

Así que tuvimos la idea: una biblioteca con las siguientes características.

OTLP nativo, sin salto por JMX

La mayoría de los stacks de observabilidad de Kafka acoplan jmx_exporter, o algo similar, como agente de la JVM, luego hacen scrape de los MBeans por un endpoint HTTP y después lo empujan a un collector.

Este plugin vive dentro del proceso de Kafka y habla OTLP directamente con el collector: un proceso menos, una superficie de configuración menos y ningún YAML de reglas de JMX que mantener.

Un plugin, ambos registros de Kafka

Los brokers de Kafka exponen métricas a través de dos sistemas paralelos: la SPI de Kafka, configurada con metric.reporters, y el registro heredado de Yammer/Coda Hale.

Varias señales internas del broker —UnderReplicatedPartitions, OfflinePartitionsCount, ActiveControllerCount y las BrokerTopicMetrics por topic— solo se registran en Yammer.

OtlpMetricReporter se conecta a ambos con una única configuración. El mismo JAR se ejecuta sin cambios en los clientes, donde el lado de Yammer se desactiva automáticamente.

A prueba de fallos por diseño: Kafka nunca se bloquea

Los callbacks de métricas como metricChange y metricRemoval solo tocan un ConcurrentHashMap en memoria. Toda la E/S ocurre en un hilo programador de tipo daemon.

Si el collector está inalcanzable, la llamada de exportación expira (timeout), el lote se descarta y el siguiente tick empieza de cero. Sin cola de reintentos, sin memoria ilimitada, sin impacto en la latencia de produce/fetch de Kafka.

El contexto del broker se convierte en labels de Prometheus de primera clase

Kafka invoca MetricsReporter.contextChange(MetricsContext) con el id del clúster, el id del nodo/broker y la versión de Kafka.

El plugin captura esos valores y los adjunta como atributos de recurso (resource attributes) de OTLP. Aparecen como labels —kafka_cluster_id, kafka_node_id o kafka_broker_id— en cada serie, de modo que by(kafka_cluster_id, kafka_node_id) funciona en PromQL sin ningún cableado adicional.

Damas y caballeros, les presentamos monedula-metrics-reporter

monedula-metrics-reporter es una biblioteca de código abierto que cumple estos requisitos, y más.

Exporta las métricas de Kafka directamente por OTLP usando gRPC o HTTP, admite Kafka 3.x y 4.x sobre Java 17+, y también puede emitir métricas de runtime de la JVM en la misma canalización.

También incluye funciones prácticas de producción como:

  • listas de permitidos (allow-listing) de métricas,
  • atributos de recurso personalizados,
  • configuración de TLS y mTLS,
  • compresión,
  • métricas de automonitorización del reporter,
  • y soporte tanto para brokers como para clientes.

El reporter también emite sus propias métricas de salud, por ejemplo:

  • monedula_reporter_export_success_total,
  • monedula_reporter_export_failure_total,
  • monedula_reporter_export_duration_ms.

Así que si la canalización del collector se rompe, no solo obtienes silencio. Obtienes señales de que el propio reporter está fallando al exportar.

El proyecto también se distribuye con una guía de inicio rápido fácil de usar que demuestra el flujo completo con Kafka, el OpenTelemetry Collector, Prometheus y Grafana. Y como los dashboards son parte del problema, incluye un conjunto curado de dashboards de Grafana listos para usar que coinciden con las métricas que produce el plugin.

Puedes encontrarlo en GitHub, compilarlo localmente y probarlo con la guía de inicio rápido. Los artefactos precompilados llegarán pronto.

Si encuentras un error o tienes una sugerencia de mejora, no dudes en crear una issue en GitHub.

Resumen

La monitorización de Kafka es más difícil de lo que debería porque Kafka expone métricas a través de dos sistemas de métricas diferentes, la mayoría de las configuraciones de producción siguen dependiendo de JMX, y cada mapeo de JMX a Prometheus crea otra capa de compatibilidad entre el broker, Prometheus y los dashboards de Grafana.

monedula-metrics-reporter adopta un enfoque distinto: se ejecuta como un reporter de métricas de Kafka, exporta las métricas de forma nativa por OTLP, gestiona ambos registros de métricas de Kafka y se distribuye con dashboards que coinciden con las métricas emitidas.

Entonces, ¿las métricas de Kafka tienen que ser tan difíciles?

Con suerte, ya no.