Why
The usual path for Kafka observability is a JMX exporter sidecar — an extra process per broker, with its own scrape window, its own failure modes, and a metric model that doesn’t quite match what the rest of the stack speaks.
monedula-metrics-reporter removes the sidecar. It plugs into Kafka’s own
MetricsReporter interface and pushes metrics directly to an OpenTelemetry
collector over OTLP — gRPC or HTTP, your call. Broker context (cluster id,
node id) is attached as resource attributes, so the same metric stream works
across brokers without per-host wiring.
All export I/O happens on a daemon thread. If the collector is slow or down, nothing reaches the threads Kafka uses to serve traffic.
For the full background — the two metric systems hiding inside Kafka, why imported Grafana dashboards so often show No Data, and how native OTLP untangles it — read Do Kafka metrics have to be so difficult?.
Configure
Drop the shadow jar into $KAFKA_HOME/libs/, then in server.properties:
metric.reporters=dev.monedula.metricsreporter.OtlpMetricReporter
otlp.metric.reporter.endpoint=http://otel-collector:4317
otlp.metric.reporter.transport=grpc
The same plugin works on Kafka clients — register it via
metric.reporters on the producer or consumer config and you get the
matching client-side stream into the same collector.
A complete demo stack (broker + collector + Prometheus + Grafana) lives
under quickstart/ in the repo.
Compatibility
Kafka 3.x and 4.x. Java 17+. Both the modern MetricsReporter SPI and the
legacy Yammer registry are wired, so you get coverage of the metrics Kafka
emits today without leaving the Yammer ones on the table.