[refactor] Decouple pinot-common test deps with FakeMetrics + plugin subclass tests; add SettableValue.getValue()#18259
Conversation
There was a problem hiding this comment.
Pull request overview
This PR relocates Yammer/Dropwizard metrics implementation tests out of pinot-common and into their respective metrics plugin modules to remove backwards (test-scope) dependencies from pinot-common onto plugin artifacts, while also adjusting a few test utilities and metrics behaviors to keep coverage intact.
Changes:
- Moved Yammer + Dropwizard Prometheus metrics tests into
pinot-yammerandpinot-dropwizardtest sources, and updated packages/paths accordingly. - Updated plugin POMs to depend on
pinot-common(includingtest-jar) for shared test bases, and removed plugin test dependencies + old test excludes frompinot-common. - Refactored metrics test utilities (
MetricValueUtils/ newYammerMetricValueUtils) and updatedConnectionFailureDetectorTestto avoid requiring plugin discovery.
Reviewed changes
Copilot reviewed 16 out of 18 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/plugin/metrics/yammer/prometheus/YammerServerPrometheusMetricsTest.java | Package move + config path update for server Prometheus metrics test. |
| pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/plugin/metrics/yammer/prometheus/YammerMinionPrometheusMetricsTest.java | Package move + config path update for minion Prometheus metrics test. |
| pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/plugin/metrics/yammer/prometheus/YammerControllerPrometheusMetricsTest.java | Package move + config path update for controller Prometheus metrics test. |
| pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/plugin/metrics/yammer/prometheus/YammerBrokerPrometheusMetricsTest.java | Package move + config path update for broker Prometheus metrics test. |
| pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/plugin/metrics/yammer/YammerMetricValueUtils.java | New Yammer-specific gauge-reading helper for moved tests. |
| pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/common/metrics/PinotMetricUtilsTest.java | Moved PinotMetricUtils tests into plugin module test sources. |
| pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/common/metrics/MetricsInspector.java | Moved registry inspection helper into plugin module test sources. |
| pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/common/metrics/AbstractMetricsTest.java | Moved + adjusted AbstractMetrics tests to use Yammer-specific gauge value utility. |
| pinot-plugins/pinot-metrics/pinot-yammer/pom.xml | Adds pinot-common + test-jar and other test deps needed by moved tests. |
| pinot-plugins/pinot-metrics/pinot-dropwizard/src/test/java/org/apache/pinot/plugin/metrics/dropwizard/prometheus/DropwizardServerPrometheusMetricsTest.java | Package move + corrected factory usage to Dropwizard. |
| pinot-plugins/pinot-metrics/pinot-dropwizard/src/test/java/org/apache/pinot/plugin/metrics/dropwizard/prometheus/DropwizardMinionPrometheusMetricsTest.java | Package move for minion dropwizard Prometheus test (still disabled). |
| pinot-plugins/pinot-metrics/pinot-dropwizard/src/test/java/org/apache/pinot/plugin/metrics/dropwizard/prometheus/DropwizardControllerPrometheusMetricsTest.java | Package move for controller dropwizard Prometheus test (still disabled). |
| pinot-plugins/pinot-metrics/pinot-dropwizard/src/test/java/org/apache/pinot/plugin/metrics/dropwizard/prometheus/DropwizardBrokerPrometheusMetricsTest.java | Package move for broker dropwizard Prometheus test (still disabled). |
| pinot-plugins/pinot-metrics/pinot-dropwizard/pom.xml | Adds pinot-common + test-jar and other test deps needed by moved tests. |
| pinot-common/src/test/java/org/apache/pinot/common/metrics/MetricValueUtils.java | Refactors test helper to read via AbstractMetrics.getGaugeValue() (implementation-agnostic). |
| pinot-common/src/test/java/org/apache/pinot/common/failuredetector/ConnectionFailureDetectorTest.java | Switches to NoopPinotMetricsRegistry to avoid requiring plugin-based registry initialization in this unit test. |
| pinot-common/src/main/java/org/apache/pinot/common/metrics/AbstractMetrics.java | Attempts to add supplier-gauge fallback behavior to getGaugeValue(). |
| pinot-common/pom.xml | Removes plugin test deps and old surefire excludes now that tests moved to plugin modules. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #18259 +/- ##
============================================
+ Coverage 63.50% 63.52% +0.01%
- Complexity 1627 1658 +31
============================================
Files 3244 3244
Lines 197367 197370 +3
Branches 30540 30540
============================================
+ Hits 125347 125384 +37
+ Misses 61983 61945 -38
- Partials 10037 10041 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 18 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
pinot-plugins/pinot-metrics/pinot-yammer/src/test/java/org/apache/pinot/common/metrics/AbstractMetricsTest.java:51
buildTestMetrics()callsPinotMetricUtils.init(config)every time it's invoked.PinotMetricUtils.init()registers new MetricsRegistryRegistrationListener instances into a static map and doesn't clear them oncleanUp(), so repeated init calls across test methods/classes can accumulate listeners and create cross-test interference. Consider initializing PinotMetricUtils once (e.g., in a@BeforeClass) and reusing it for the whole test class, or avoidinginit()here if it isn't required for these tests.
Jackie-Jiang
left a comment
There was a problem hiding this comment.
This change is touching production class. If the change is required, please revise the PR title and description
…eMetrics
pinot-common/pom.xml previously pulled in pinot-yammer and pinot-dropwizard
at test scope solely to compile a handful of yammer/dropwizard-specific test
classes. The direction is backwards — plugin modules should depend on
pinot-common, not the other way around — and it blocked making pinot-common
self-contained for test purposes.
This change relocates plugin-specific tests into their plugin modules and
introduces an abstract, implementation-agnostic AbstractMetricsTest that each
metrics implementation runs against its own registry. pinot-common itself
exercises the base test via an in-memory FakeMetrics implementation, so no
plugin module has to be on pinot-common's test classpath.
pinot-common/
Dropped pinot-yammer / pinot-dropwizard test-scope deps; removed the
surefire excludes that were carrying those tests.
AbstractMetrics: added public getMetricPrefix() so test helpers can
compose PinotMetricNames without reaching into protected fields.
test: MetricValueUtils refactored to route through
AbstractMetrics.getGaugeValue() — implementation-agnostic.
test: ConnectionFailureDetectorTest constructs YammerMetricsFactory
directly instead of relying on ServiceLoader; no longer requires the
plugin for service discovery.
test: AbstractMetricsTest is now an abstract base with hooks
(metricsFactoryClassName, buildRegistry, createInspector, getGaugeValue).
test: MetricsInspector is an abstract class with lastMetric,
getTimerSumMs, getMeteredCount.
test: PinotMetricUtilsTest now bootstraps with FakeMetricsFactory rather
than assuming yammer on the classpath.
test: plugin/metrics/fake/ — in-memory FakePinotMetricsRegistry,
FakeMetricsFactory (no JMX to avoid MBean name collisions across tests),
Fake wrapper types, FakeMetricsInspector, and the concrete
FakeMetricsAbstractMetricsTest that runs the base suite.
Both AbstractMetricsTest and PinotMetricUtilsTest have @afterclass
PinotMetricUtils.cleanUp() so the static factory is torn down between
test classes.
pinot-plugins/pinot-metrics/pinot-yammer/
Added pinot-common:test-jar (+ its transitive test deps) so the plugin
module can extend the shared tests.
Relocated the four Yammer prometheus tests from
pinot-common/src/test/.../metrics/prometheus/yammer/ into
pinot-plugins/pinot-metrics/pinot-yammer/src/test/.../prometheus/.
Renamed the yammer-flavored MetricValueUtils to YammerMetricValueUtils
to avoid an FQN clash with the impl-agnostic MetricValueUtils that stays
in pinot-common.
YammerMetricsInspector moved next to the registry implementation.
YammerAbstractMetricsTest subclasses the shared AbstractMetricsTest with
the real YammerMetricsRegistry.
pinot-plugins/pinot-metrics/pinot-dropwizard/
Relocated the four Dropwizard prometheus tests into the plugin module.
Preserved @test(enabled = false) but fixed a copy-paste bug in
DropwizardServerPrometheusMetricsTest.getPinotMetricsFactory that
returned YammerMetricsFactory.
DropwizardMetricValueUtils mirrors the yammer helper.
DropwizardMetricsInspector derives timer sum from snapshot.getValues
since Dropwizard's Timer has no sum() method.
DropwizardAbstractMetricsTest subclasses the shared AbstractMetricsTest.
9a10983 to
9df2a90
Compare
- PinotMetricUtilsTest.testPinotMetricName: init PinotMetricUtils with FakeMetricsFactory at the start of the test so it isn't order-dependent on whatever factory a prior test left behind (noop vs real). - FakePinotMetricsRegistry.newHistogram: throw UnsupportedOperationException instead of returning null. Returning null violates the PinotMetricsRegistry contract and can surface as an NPE if a future test ever asks for a histogram. - FakeMetricsFactory: drop @autoservice(PinotMetricsFactory.class). PinotMetricUtils discovery is driven by @MetricsFactory reflection scanning, not ServiceLoader, so the auto-service META-INF/services entry was dead code that also risked leaking the fake factory into consumers of pinot-common's test-jar.
CI (MergeRollupMinionClusterIntegrationTest) was failing because the refactored MetricValueUtils only read from AbstractMetrics.getGaugeValue, which returns null for gauges registered via pure-supplier paths (setOrUpdateGauge(Supplier), setOrUpdateGauge(long), addCallbackGauge) — those paths don't populate the internal _gaugeValues map. Fall back to looking the metric up in the registry and reading it via the SettableValue SPI, which is the common supertype of YammerSettableGauge and DropwizardSettableGauge. - pinot-spi: add getValue() to SettableValue. PinotGauge.getValue() defaults to value() so every existing PinotGauge impl continues to work without change. - pinot-yammer: add getValue() to YammerSettableGauge (delegates to value()). DropwizardSettableGauge already has getValue() from Dropwizard's SettableGauge — no change needed. - pinot-common: MetricValueUtils tries AbstractMetrics.getGaugeValue first (fast path for _gaugeValues-backed gauges) then falls back to registry.allMetrics().get(name).getMetric() cast to SettableValue. Uses AbstractMetrics.getMetricPrefix() + metrics.getClass() to construct the PinotMetricName, so the helper stays plugin-agnostic.
Summary
Untangle the circular test-scope dependency where
pinot-commondepended onpinot-yammerandpinot-dropwizardfor its own tests. Plugin-specific tests move into their plugin modules; sharedAbstractMetricstest logic stays inpinot-commonand runs against an in-memory fake registry, with each plugin subclassing the base suite for its own registry.Why
pinot-common/pom.xmlpulled inpinot-yammerandpinot-dropwizardat<scope>test</scope>solely because a handful of tests underpinot-common/src/test/.../metrics/exercised plugin-specific implementations. This is backwards — plugin modules should depend onpinot-common, not the other way around — and it blocked follow-up work to makepinot-commonself-contained.What changed
pinot-commonpinot-yammerandpinot-dropwizardtest-scope deps; removed the surefire excludes that were carrying Dropwizard prometheus tests.AbstractMetrics.getMetricPrefix()getter so test helpers can compose aPinotMetricNamewithout reaching into the protected field (or aninstanceofcascade).AbstractMetricsTestis now an abstract base with hooksmetricsFactoryClassName(),buildRegistry(),createInspector(),getGaugeValue(). Every@Teststays generic.MetricsInspectoris now an abstract class (lastMetric,getTimerSumMs,getMeteredCount). Plugin-specific concrete subclasses live in each plugin module.MetricValueUtilsno longer casts toYammerSettableGauge— routes throughAbstractMetrics.getGaugeValue()so it's implementation-agnostic.PinotMetricUtilsTestnow bootstraps with the newFakeMetricsFactoryinstead of assuming Yammer on the classpath.ConnectionFailureDetectorTestconstructsNoopPinotMetricsRegistrydirectly, removing its dependence on ServiceLoader-discovered factories.pinot-common/src/test/java/org/apache/pinot/plugin/metrics/fake/:FakePinotMetricsRegistry— in-memory, with listener replay semantics per the SPI contract.FakeMetricsFactory— no JMX reporter (intentional, to avoid cross-test MBean collisions).FakePinotGauge/Meter/Counter/Timer,FakePinotMetricName, plusFakeMetricsInspector.FakeMetricsAbstractMetricsTest— concrete subclass that runs the base suite against the fake registry.@AfterClass PinotMetricUtils.cleanUp()on bothAbstractMetricsTestandPinotMetricUtilsTestso the static factory is torn down between test classes.pinot-plugins/pinot-metrics/pinot-yammerpinot-common+pinot-common:test-jarat test scope so the plugin module can extend the shared tests.pinot-common/src/test/.../prometheus/yammer/into the plugin module.MetricValueUtils→YammerMetricValueUtilsto avoid an FQN clash with the impl-agnosticMetricValueUtilsthat stays inpinot-common.YammerMetricsInspectormoved next to the realYammerMetricsRegistry.YammerAbstractMetricsTestsubclasses the sharedAbstractMetricsTestwith a realYammerMetricsRegistryand usesYammerMetricValueUtilsfor gauge reads.pinot-plugins/pinot-metrics/pinot-dropwizardpinot-common:test-jarat test scope.@Test(enabled = false)on the ones that were disabled, and fixed a latent copy-paste bug inDropwizardServerPrometheusMetricsTest.getPinotMetricsFactory()that was returningYammerMetricsFactory.DropwizardMetricValueUtilsmirrors the Yammer helper.DropwizardMetricsInspector— Timer sum derived fromsnapshot.getValues()summation (Dropwizard'sTimerhas nosum()method).DropwizardAbstractMetricsTestsubclasses the sharedAbstractMetricsTest.Behavior notes
MetricValueUtilsbehavior change: now routes throughAbstractMetrics.getGaugeValue(), which only reads the internal_gaugeValuesmap. For gauges registered via pure supplier paths (setOrUpdateGauge(Supplier)/setOrUpdateGauge(long)/addCallbackGauge),_gaugeValuesis not populated — soMetricValueUtils.getGaugeValuereturns0andgaugeExistsreturnsfalse. Upstream Fix flaky MergeRollupMinionClusterIntegrationTest gauge assertions #18260 already landed the required adjustment forMergeRollupMinionClusterIntegrationTest; other test consumers reading supplier-registered gauges viaMetricValueUtilsshould switch toYammer/DropwizardMetricValueUtilsor read from the registry directly.AbstractMetrics.getMetricPrefix()getter.Test plan
./mvnw -pl pinot-common test -Dtest=FakeMetricsAbstractMetricsTest— 15/15 pass./mvnw -pl pinot-common test -Dtest=PinotMetricUtilsTest— 6/6 pass./mvnw -pl pinot-common test -Dtest=ConnectionFailureDetectorTest— 4/4 pass./mvnw -pl pinot-plugins/pinot-metrics/pinot-yammer test— all pass (incl.YammerAbstractMetricsTest15/15 + prometheus suites)./mvnw -pl pinot-plugins/pinot-metrics/pinot-dropwizard test— all pass (incl.DropwizardAbstractMetricsTest15/15)./mvnw -pl pinot-controller test -Dtest=SegmentStatusCheckerTest— 23/23 pass (external consumer ofMetricValueUtils)./mvnw spotless:check checkstyle:check license:check -pl pinot-common,pinot-plugins/pinot-metrics/pinot-yammer,pinot-plugins/pinot-metrics/pinot-dropwizard— clean