Copilot commented on code in PR #18259:
URL: https://github.com/apache/pinot/pull/18259#discussion_r3114373729
##########
pinot-common/src/test/java/org/apache/pinot/common/metrics/PinotMetricUtilsTest.java:
##########
@@ -21,30 +21,40 @@
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import org.apache.pinot.plugin.metrics.fake.FakeMetricsFactory;
import org.apache.pinot.spi.env.PinotConfiguration;
import org.apache.pinot.spi.metrics.MetricsRegistryRegistrationListener;
import org.apache.pinot.spi.metrics.PinotMeter;
import org.apache.pinot.spi.metrics.PinotMetricName;
import org.apache.pinot.spi.metrics.PinotMetricUtils;
import org.apache.pinot.spi.metrics.PinotMetricsRegistry;
import org.testng.Assert;
+import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
+import static
org.apache.pinot.spi.utils.CommonConstants.CONFIG_OF_METRICS_FACTORY_CLASS_NAME;
+
public class PinotMetricUtilsTest {
+ @AfterClass
+ public void cleanUpMetricsFactory() {
+ PinotMetricUtils.cleanUp();
+ }
Review Comment:
`testPinotMetricName()` relies on whatever `PinotMetricUtils` factory was
last initialized by other tests. If this test runs before any
`PinotMetricUtils.init(...)`, the factory is still `PinotMetricsFactory.Noop`,
and two `makePinotMetricName(...)` calls will return non-equal lambda
instances, making the test order-dependent/flaky. Consider initializing
`PinotMetricUtils` with `FakeMetricsFactory` in a `@BeforeMethod` (or at the
start of `testPinotMetricName`) and cleaning up per-test to keep tests isolated.
##########
pinot-common/src/test/java/org/apache/pinot/plugin/metrics/fake/FakeMetricsFactory.java:
##########
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.plugin.metrics.fake;
+
+import com.google.auto.service.AutoService;
+import java.util.function.Function;
+import org.apache.pinot.spi.annotations.metrics.MetricsFactory;
+import org.apache.pinot.spi.annotations.metrics.PinotMetricsFactory;
+import org.apache.pinot.spi.env.PinotConfiguration;
+import org.apache.pinot.spi.metrics.PinotGauge;
+import org.apache.pinot.spi.metrics.PinotJmxReporter;
+import org.apache.pinot.spi.metrics.PinotMetricName;
+import org.apache.pinot.spi.metrics.PinotMetricsRegistry;
+
+
+/**
+ * A test-only {@link PinotMetricsFactory} backed by the in-memory {@link
FakePinotMetricsRegistry}. Used by
+ * pinot-common tests so they can exercise {@code AbstractMetrics} without
depending on a plugin module.
+ */
+@AutoService(PinotMetricsFactory.class)
+@MetricsFactory
Review Comment:
`FakeMetricsFactory` is test-only, but
`@AutoService(PinotMetricsFactory.class)` will generate a `META-INF/services`
entry and can make this factory discoverable via `ServiceLoader` (e.g., for
`CompoundPinotMetricsFactory` when using the SERVICE_LOADER algorithm) in any
test runtime that includes `pinot-common`'s `test-jar`. Since
`PinotMetricUtils` discovery here is already driven by `@MetricsFactory` +
explicit `factory.className`, consider removing `@AutoService` to avoid
accidental inclusion of the fake factory in unrelated tests.
##########
pinot-common/src/test/java/org/apache/pinot/plugin/metrics/fake/FakePinotMetricsRegistry.java:
##########
@@ -0,0 +1,144 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.plugin.metrics.fake;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+import org.apache.pinot.spi.metrics.PinotCounter;
+import org.apache.pinot.spi.metrics.PinotGauge;
+import org.apache.pinot.spi.metrics.PinotHistogram;
+import org.apache.pinot.spi.metrics.PinotMeter;
+import org.apache.pinot.spi.metrics.PinotMetric;
+import org.apache.pinot.spi.metrics.PinotMetricName;
+import org.apache.pinot.spi.metrics.PinotMetricsRegistry;
+import org.apache.pinot.spi.metrics.PinotMetricsRegistryListener;
+import org.apache.pinot.spi.metrics.PinotTimer;
+
+
+/**
+ * In-memory, no-JMX {@link PinotMetricsRegistry} for unit-testing {@code
AbstractMetrics}-derived classes without
+ * requiring a real metrics plugin on the classpath.
+ */
+public class FakePinotMetricsRegistry implements PinotMetricsRegistry {
+ private final Map<PinotMetricName, PinotMetric> _metrics = new
ConcurrentHashMap<>();
+ private final List<Listener> _listeners = new CopyOnWriteArrayList<>();
+
+ @Override
+ public <T> PinotGauge<T> newGauge(PinotMetricName name, PinotGauge<T> gauge)
{
+ @SuppressWarnings("unchecked")
+ PinotGauge<T> existing = (PinotGauge<T>) _metrics.get(name);
+ if (existing != null) {
+ return existing;
+ }
+ _metrics.put(name, gauge);
+ notifyAdded(name, gauge);
+ return gauge;
+ }
+
+ @Override
+ public PinotMeter newMeter(PinotMetricName name, String eventType, TimeUnit
unit) {
+ return (PinotMeter) _metrics.computeIfAbsent(name, n -> {
+ FakePinotMeter meter = new FakePinotMeter(eventType, unit);
+ notifyAdded(n, meter);
+ return meter;
+ });
+ }
+
+ @Override
+ public PinotCounter newCounter(PinotMetricName name) {
+ return (PinotCounter) _metrics.computeIfAbsent(name, n -> {
+ FakePinotCounter counter = new FakePinotCounter();
+ notifyAdded(n, counter);
+ return counter;
+ });
+ }
+
+ @Override
+ public PinotTimer newTimer(PinotMetricName name, TimeUnit durationUnit,
TimeUnit rateUnit) {
+ return (PinotTimer) _metrics.computeIfAbsent(name, n -> {
+ FakePinotTimer timer = new FakePinotTimer(durationUnit, rateUnit);
+ notifyAdded(n, timer);
+ return timer;
+ });
+ }
+
+ @Override
+ public PinotHistogram newHistogram(PinotMetricName name, boolean biased) {
+ return null;
Review Comment:
`newHistogram(...)` currently returns `null`, which violates the
`PinotMetricsRegistry` contract and can turn into a hard-to-debug
`NullPointerException` if any code path under test ever creates a histogram
(e.g., via `PinotMetricUtils.make...`). Prefer either implementing a minimal
`FakePinotHistogram` or throwing `UnsupportedOperationException` with a clear
message so failures are explicit.
```suggestion
throw new UnsupportedOperationException(
"FakePinotMetricsRegistry does not support histograms: " + name);
```
##########
pinot-common/src/main/java/org/apache/pinot/common/metrics/AbstractMetrics.java:
##########
@@ -94,6 +94,10 @@ public PinotMetricsRegistry getMetricsRegistry() {
return _metricsRegistry;
}
+ public String getMetricPrefix() {
+ return _metricPrefix;
+ }
Review Comment:
The PR description mentions a production fix to
`AbstractMetrics.getGaugeValue()` (fallback to registry lookup for
supplier-based gauges), but the current diff for this file only adds
`getMetricPrefix()` and `getGaugeValue(...)` still only reads from
`_gaugeValues`. Either update the PR description to reflect the actual scope,
or include the `getGaugeValue()` fallback change in this PR as described.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]