Skip to content

Add native Micrometer metrics backend (Prometheus + optional JMX legs)#18786

Draft
gortiz wants to merge 1 commit into
apache:masterfrom
gortiz:feature/micrometer-metrics
Draft

Add native Micrometer metrics backend (Prometheus + optional JMX legs)#18786
gortiz wants to merge 1 commit into
apache:masterfrom
gortiz:feature/micrometer-metrics

Conversation

@gortiz

@gortiz gortiz commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new pinot-micrometer metrics plugin (pinot-plugins/pinot-metrics/pinot-micrometer) implementing the existing metrics SPI as a genuinely native Micrometer backend — a step toward adopting the de-facto JVM metrics standard.

A single Micrometer CompositeMeterRegistry natively fans each meter to its enabled, config-toggled export legs (no Dropwizard store, no mirroring):

  • Prometheus leg (opt-in): a Micrometer PrometheusMeterRegistry exporting directly in Prometheus exposition format (no JMX hop), optionally over an HTTP scrape endpoint.
  • JMX leg (opt-in): a Micrometer JmxMeterRegistry exposing meters as MBeans under Micrometer-native names.

The standard Micrometer JVM/system binders (memory, GC, threads, class loader, CPU, uptime, file descriptors) are bound to the composite, so basic JVM observability is exported whenever a leg is enabled.

⚠️ Metric names/resolutions intentionally differ from the legacy backends

Unlike pinot-yammer/pinot-dropwizard, this backend does not reproduce the legacy JMX-derived Prometheus names. It uses native Micrometer conventions, which are a different shape:

Metric Legacy (Yammer/Dropwizard) Native Micrometer
Meter _Count, _MeanRate, _OneMinuteRate, _FiveMinuteRate, _FifteenMinuteRate (5 series, server-side EWMA) single cumulative _total; no EWMA rates (rate computed downstream via Prometheus rate())
Timer the meter rate set + _Min/_Max/_Mean/_StdDev + _50th…_999thPercentile _count / _sum / _max (+ optional client-side percentiles); no EWMA rates
Gauge _Value a single bare series

This divergence is deliberate. Callers that need the exact legacy names will compose Yammer (→ JMX) + Micrometer (→ Prometheus/everything else) via the compound registry (a separate follow-up). The default metrics factory (Yammer) is unchanged; this backend is strictly opt-in via the factory class name.

Configuration

All keys under pinot.metrics.micrometer.:

Key Default Meaning
prometheus.enabled false enable the direct-Prometheus leg
prometheus.port 0 scrape-endpoint HTTP port (0 = no server)
prometheus.path /metrics scrape-endpoint path
jmx.enabled false enable the (Micrometer-native) JMX leg

If no leg is enabled the registry logs a WARN (meters are accepted but nothing is exported).

Implementation notes

  • Gauges are registered with a strong reference to their value holder. Micrometer holds gauge state via a WeakReference by default and the SPI caller (AbstractMetrics) discards the returned wrapper, so without this gauges would silently decay to NaN after GC. Covered by a dedicated GC regression test.
  • PinotMetered rate methods return NaN (no EWMA equivalent in Micrometer).
  • makePinotJmxReporter is a no-op (the JmxMeterRegistry exports continuously once in the composite); addListener is a documented no-op (no native equivalent).

Testing

Native-behavior tests assert the per-type Prometheus series + values, JVM metrics presence, the HTTP scrape endpoint, NaN-safety, gauge-survives-GC, and the JMX leg's MBeans. MicrometerVsLegacyDifferenceTest instantiates both a Yammer and a Micrometer registry and characterizes the divergence (legacy meanRate() finite vs native NaN; native scrape carries the native suffixes and none of the legacy CamelCase ones). All green.

Release Notes

Adds an opt-in, native Micrometer metrics backend that exports directly to Prometheus (and/or Micrometer-native JMX) with standard JVM/system metrics. Its exported metric names/resolutions follow Micrometer conventions and differ from the legacy Yammer/Dropwizard names — it is opt-in and does not affect the default backend. Operators needing the exact legacy names can combine backends via the compound registry.

@gortiz gortiz force-pushed the feature/micrometer-metrics branch from 13d677f to 2b8838b Compare June 17, 2026 11:33
@codecov-commenter

codecov-commenter commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.78%. Comparing base (b27a3ad) to head (1ba1255).
⚠️ Report is 16 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##             master   #18786   +/-   ##
=========================================
  Coverage     64.78%   64.78%           
  Complexity     1309     1309           
=========================================
  Files          3380     3380           
  Lines        209544   209630   +86     
  Branches      32797    32822   +25     
=========================================
+ Hits         135746   135809   +63     
- Misses        62870    62888   +18     
- Partials      10928    10933    +5     
Flag Coverage Δ
custom-integration1 100.00% <ø> (ø)
integration 100.00% <ø> (ø)
integration1 100.00% <ø> (ø)
integration2 0.00% <ø> (ø)
java-21 64.78% <ø> (+<0.01%) ⬆️
temurin 64.78% <ø> (+<0.01%) ⬆️
unittests 64.78% <ø> (+<0.01%) ⬆️
unittests1 56.97% <ø> (+0.01%) ⬆️
unittests2 37.26% <ø> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Introduces a new `pinot-micrometer` metrics plugin implementing the metrics SPI
as a genuinely native Micrometer backend. A single CompositeMeterRegistry fans
each meter to its enabled, config-toggled export legs:

- Prometheus leg (opt-in): a Micrometer PrometheusMeterRegistry exporting directly
  in Prometheus exposition format, optionally over an HTTP scrape endpoint.
- JMX leg (opt-in): a Micrometer JmxMeterRegistry exposing meters as MBeans under
  Micrometer-native names.

The standard Micrometer JVM/system binders (memory, GC, threads, class loader,
CPU, uptime, file descriptors) are bound to the composite so basic JVM
observability is exported whenever a leg is enabled.

Exported metric names/resolutions follow Micrometer conventions and INTENTIONALLY
differ from the legacy Yammer/Dropwizard JMX names (e.g. a meter exports a single
cumulative `_total` with no EWMA rate series; a timer exports `_count`/`_sum`/`_max`).
Callers needing the exact legacy names compose Yammer + Micrometer via the compound
registry. The default factory (Yammer) is unchanged; this backend is opt-in.

Gauges are registered with a strong reference to their value holder so they do not
silently decay to NaN after GC (Micrometer holds gauge state weakly by default).

Config keys (pinot.metrics.micrometer.*): prometheus.enabled, prometheus.port,
prometheus.path, jmx.enabled.

Tests: native-behavior tests (per-type Prometheus series + values, JVM metrics, HTTP
endpoint, NaN-safety, gauge-survives-GC, JMX-leg MBeans) and a
MicrometerVsLegacyDifferenceTest that characterizes how the native series differ
from the legacy Yammer/Dropwizard backends.
@gortiz gortiz force-pushed the feature/micrometer-metrics branch from 2b8838b to 1ba1255 Compare June 17, 2026 14:49
@gortiz gortiz changed the title Add Micrometer metrics backend (JMX parity + opt-in direct Prometheus export) Add native Micrometer metrics backend (Prometheus + optional JMX legs) Jun 17, 2026
@gortiz gortiz marked this pull request as draft June 18, 2026 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants