This is an automated email from the ASF dual-hosted git repository.

mlbiscoc pushed a commit to branch feature/SOLR-17458-rebased
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/feature/SOLR-17458-rebased by 
this push:
     new e4af8c9bd81 Broken tests from closing meter providers on core unload 
and reload (#3707)
e4af8c9bd81 is described below

commit e4af8c9bd8101c01bb90df37e7252837c1726aa0
Author: Matthew Biscocho <[email protected]>
AuthorDate: Wed Oct 1 09:05:41 2025 -0400

    Broken tests from closing meter providers on core unload and reload (#3707)
    
    * Broken tests from core unload and reload
    
    * cleanup
    
    * Fix other broken tests and remove test
    
    * Don't close registry in CoreMetricManager
---
 .../randomization/policies/solr-tests.policy       | 10 ++-
 .../src/java/org/apache/solr/core/SolrCore.java    | 12 ++--
 .../apache/solr/metrics/SolrCoreMetricManager.java | 32 ++++-----
 .../org/apache/solr/metrics/SolrMetricManager.java | 16 ++---
 .../solr/metrics/otel/NoopMetricExporter.java      | 46 ------------
 .../src/java/org/apache/solr/update/PeerSync.java  |  3 +-
 .../org/apache/solr/update/PeerSyncWithLeader.java |  3 +-
 .../src/java/org/apache/solr/update/UpdateLog.java |  5 +-
 .../org/apache/solr/core/RequestHandlersTest.java  | 16 ++---
 .../solr/handler/admin/StatsReloadRaceTest.java    | 82 ++++++++++++----------
 .../solr/metrics/SolrCoreMetricManagerTest.java    | 27 +------
 .../solr/metrics/SolrMetricsIntegrationTest.java   | 51 +++++---------
 .../org/apache/solr/search/TestSolrCachePerf.java  |  3 +-
 .../solr/opentelemetry/OtlpExporterFactory.java    | 11 ++-
 solr/server/etc/security.policy                    |  6 +-
 .../core/MockQuerySenderListenerReqHandler.java    |  8 ++-
 16 files changed, 126 insertions(+), 205 deletions(-)

diff --git a/gradle/testing/randomization/policies/solr-tests.policy 
b/gradle/testing/randomization/policies/solr-tests.policy
index 2d3246c6d9b..5e7f2f81d0b 100644
--- a/gradle/testing/randomization/policies/solr-tests.policy
+++ b/gradle/testing/randomization/policies/solr-tests.policy
@@ -130,11 +130,11 @@ grant {
   permission javax.management.MBeanServerPermission "findMBeanServer";
   permission javax.management.MBeanServerPermission "releaseMBeanServer";
   permission javax.management.MBeanTrustPermission "register";
-  
+
   // needed by crossdc
   permission javax.security.auth.AuthPermission "getLoginConfiguration";
   permission javax.security.auth.AuthPermission "setLoginConfiguration";
-  
+
   // needed by benchmark
   permission java.security.SecurityPermission "insertProvider";
 
@@ -206,7 +206,7 @@ grant {
 
 // additional permissions based on system properties set by /bin/solr
 // NOTE: if the property is not set, the permission entry is ignored.
-grant {  
+grant {
   permission java.io.FilePermission "${solr.jetty.keystore}", 
"read,write,delete,readlink";
   permission java.io.FilePermission "${solr.jetty.keystore}${/}-", 
"read,write,delete,readlink";
 
@@ -277,3 +277,7 @@ grant {
   // Allow testing effects of customized or bug-fixed dependencies locally 
(also need to add mavenLocal() to build)
   permission java.io.FilePermission "${user.home}${/}.m2${/}repository${/}-", 
"read";
 };
+
+grant {
+    permission jdk.jfr.FlightRecorderPermission "accessFlightRecorder";
+};
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java 
b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index 2d31429eab4..2f99f4be8af 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -1315,7 +1315,7 @@ public class SolrCore implements SolrInfoBean, Closeable {
       newUpdateHandler = createUpdateHandler(updateHandlerClass, 
updateHandler);
     }
     if (newUpdateHandler != null) {
-      coreMetricManager.registerMetricProducer("updateHandler", 
newUpdateHandler);
+      coreMetricManager.registerMetricProducer(newUpdateHandler, 
Attributes.empty());
     }
     infoRegistry.put("updateHandler", newUpdateHandler);
     return newUpdateHandler;
@@ -3255,7 +3255,8 @@ public class SolrCore implements SolrInfoBean, Closeable {
       if (registry != null) registry.put(info.name, o);
       if (o instanceof SolrMetricProducer) {
         coreMetricManager.registerMetricProducer(
-            type.getSimpleName() + "." + info.name, (SolrMetricProducer) o);
+            (SolrMetricProducer) o,
+            Attributes.of(PLUGIN_NAME_ATTR, type.getSimpleName() + "." + 
info.name));
       }
       if (o instanceof CircuitBreaker) {
         if (o instanceof SolrCoreAware) {
@@ -3273,7 +3274,8 @@ public class SolrCore implements SolrInfoBean, Closeable {
   public void initDefaultPlugin(Object plugin, Class<?> type) {
     if (plugin instanceof SolrMetricProducer) {
       coreMetricManager.registerMetricProducer(
-          type.getSimpleName() + ".default", (SolrMetricProducer) plugin);
+          (SolrMetricProducer) plugin,
+          Attributes.of(PLUGIN_NAME_ATTR, type.getSimpleName() + ".default"));
     }
   }
 
@@ -3583,7 +3585,9 @@ public class SolrCore implements SolrInfoBean, Closeable {
     infoRegistry.put(name, solrInfoBean);
 
     if (solrInfoBean != null) {
-      coreMetricManager.registerMetricProducer(name, solrInfoBean);
+      Attributes attributes =
+          (name.startsWith("/")) ? Attributes.of(HANDLER_ATTR, name) : 
Attributes.empty();
+      coreMetricManager.registerMetricProducer(solrInfoBean, attributes);
     }
   }
 
diff --git 
a/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java 
b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
index 683e71b283e..9d859d4f5a9 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
@@ -16,10 +16,9 @@
  */
 package org.apache.solr.metrics;
 
-import static org.apache.solr.metrics.SolrMetricProducer.HANDLER_ATTR;
-
 import com.codahale.metrics.MetricRegistry;
 import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.Attributes;
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -57,7 +56,7 @@ public class SolrCoreMetricManager implements Closeable {
   // rename
   private final List<MetricProducerInfo> registeredProducers = new 
ArrayList<>();
 
-  private record MetricProducerInfo(SolrMetricProducer producer, String scope) 
{}
+  private record MetricProducerInfo(SolrMetricProducer producer, Attributes 
attributes) {}
 
   /**
    * Constructs a metric manager.
@@ -132,11 +131,10 @@ public class SolrCoreMetricManager implements Closeable {
 
     registeredProducers.forEach(
         metricProducer -> {
-          var producerAttributes = core.getCoreAttributes().toBuilder();
-          if (metricProducer.scope().startsWith("/"))
-            producerAttributes.put(HANDLER_ATTR, metricProducer.scope);
           metricProducer.producer.initializeMetrics(
-              solrMetricsContext, producerAttributes.build(), 
metricProducer.scope);
+              solrMetricsContext,
+              
metricProducer.attributes.toBuilder().putAll(core.getCoreAttributes()).build(),
+              "");
         });
   }
 
@@ -145,29 +143,28 @@ public class SolrCoreMetricManager implements Closeable {
    * set of attributes for core level metrics. All metric producers are 
tracked for re-registering
    * in the case of core swapping/renaming
    *
-   * @param scope the scope of the metrics to be registered (e.g. 
`/admin/ping`)
    * @param producer producer of metrics to be registered
+   * @param attributes
    */
-  public void registerMetricProducer(String scope, SolrMetricProducer 
producer) {
-    if (scope == null || producer == null) {
+  public void registerMetricProducer(SolrMetricProducer producer, Attributes 
attributes) {
+    if (attributes == null || producer == null) {
       throw new IllegalArgumentException(
           "registerMetricProducer() called with illegal arguments: "
-              + "scope = "
-              + scope
+              + "attributes = "
+              + attributes
               + ", producer = "
               + producer);
     }
 
     // Track this producer for potential re-initialization during core rename
-    registeredProducers.add(new MetricProducerInfo(producer, scope));
+    registeredProducers.add(new MetricProducerInfo(producer, attributes));
 
     // TODO: We initialize metrics with attributes of the core. This happens 
again in
     // reregisterCoreMetrics
     // There is some possible improvement that can be done here to not have to 
duplicate code in
     // reregisterCoreMetrics
-    var attributesBuilder = core.getCoreAttributes().toBuilder();
-    if (scope.startsWith("/")) attributesBuilder.put(HANDLER_ATTR, scope);
-    producer.initializeMetrics(solrMetricsContext, attributesBuilder.build(), 
scope);
+    producer.initializeMetrics(
+        solrMetricsContext, 
attributes.toBuilder().putAll(core.getCoreAttributes()).build(), "");
   }
 
   /** Return the registry used by this SolrCore. */
@@ -190,9 +187,6 @@ public class SolrCoreMetricManager implements Closeable {
     }
     metricManager.unregisterGauges(
         solrMetricsContext.getRegistryName(), solrMetricsContext.getTag());
-
-    metricManager.removeRegistry(solrMetricsContext.getRegistryName());
-    registeredProducers.clear();
   }
 
   public SolrMetricsContext getSolrMetricsContext() {
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java 
b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
index 43da56a7f75..fb2280a8cd6 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
@@ -98,7 +98,6 @@ import org.apache.solr.core.SolrResourceLoader;
 import org.apache.solr.logging.MDCLoggingContext;
 import org.apache.solr.metrics.otel.FilterablePrometheusMetricReader;
 import org.apache.solr.metrics.otel.MetricExporterFactory;
-import org.apache.solr.metrics.otel.NoopMetricExporter;
 import org.apache.solr.metrics.otel.OtelUnit;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -889,12 +888,11 @@ public class SolrMetricManager {
    */
   // NOCOMMIT: Remove this
   public void removeRegistry(String registry) {
-    meterProviderAndReaders.computeIfPresent(
-        enforcePrefix(registry),
-        (key, meterAndReader) -> {
-          IOUtils.closeQuietly(meterAndReader.sdkMeterProvider());
-          return null;
-        });
+    String key = enforcePrefix(registry);
+    MeterProviderAndReaders mpr = meterProviderAndReaders.remove(key);
+    if (mpr != null) {
+      IOUtils.closeQuietly(mpr.sdkMeterProvider());
+    }
   }
 
   /** Close all meter providers and their associated metric readers. */
@@ -1769,7 +1767,7 @@ public class SolrMetricManager {
   }
 
   private MetricExporter loadMetricExporter(SolrResourceLoader loader) {
-    if (!OTLP_EXPORTER_ENABLED) return new NoopMetricExporter();
+    if (!OTLP_EXPORTER_ENABLED) return null;
     try {
       MetricExporterFactory exporterFactory =
           loader.newInstance(
@@ -1778,7 +1776,7 @@ public class SolrMetricManager {
     } catch (SolrException e) {
       log.error(
           "Could not load OTLP exporter. Check that the Open Telemetry module 
is enabled.", e);
-      return new NoopMetricExporter();
+      return null;
     }
   }
 
diff --git 
a/solr/core/src/java/org/apache/solr/metrics/otel/NoopMetricExporter.java 
b/solr/core/src/java/org/apache/solr/metrics/otel/NoopMetricExporter.java
deleted file mode 100644
index 578a8f5a01c..00000000000
--- a/solr/core/src/java/org/apache/solr/metrics/otel/NoopMetricExporter.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.solr.metrics.otel;
-
-import io.opentelemetry.sdk.common.CompletableResultCode;
-import io.opentelemetry.sdk.metrics.InstrumentType;
-import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
-import io.opentelemetry.sdk.metrics.data.MetricData;
-import io.opentelemetry.sdk.metrics.export.MetricExporter;
-import java.util.Collection;
-
-public class NoopMetricExporter implements MetricExporter {
-  @Override
-  public CompletableResultCode export(Collection<MetricData> metrics) {
-    return CompletableResultCode.ofSuccess();
-  }
-
-  @Override
-  public CompletableResultCode flush() {
-    return CompletableResultCode.ofSuccess();
-  }
-
-  @Override
-  public CompletableResultCode shutdown() {
-    return CompletableResultCode.ofSuccess();
-  }
-
-  @Override
-  public AggregationTemporality getAggregationTemporality(InstrumentType 
instrumentType) {
-    return AggregationTemporality.CUMULATIVE;
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/update/PeerSync.java 
b/solr/core/src/java/org/apache/solr/update/PeerSync.java
index a58d3b9c66c..90fdb7674aa 100644
--- a/solr/core/src/java/org/apache/solr/update/PeerSync.java
+++ b/solr/core/src/java/org/apache/solr/update/PeerSync.java
@@ -134,8 +134,7 @@ public class PeerSync implements SolrMetricProducer {
     shardHandler = shardHandlerFactory.getShardHandler();
     this.updater = new Updater(msg(), core);
 
-    core.getCoreMetricManager()
-        .registerMetricProducer(SolrInfoBean.Category.REPLICATION.toString(), 
this);
+    core.getCoreMetricManager().registerMetricProducer(this, 
Attributes.empty());
   }
 
   public static final String METRIC_SCOPE = "peerSync";
diff --git a/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java 
b/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java
index 5a8e4186b29..d01a5bf51cd 100644
--- a/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java
+++ b/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java
@@ -89,8 +89,7 @@ public class PeerSyncWithLeader implements SolrMetricProducer 
{
 
     this.updater = new PeerSync.Updater(msg(), core);
 
-    core.getCoreMetricManager()
-        .registerMetricProducer(SolrInfoBean.Category.REPLICATION.toString(), 
this);
+    core.getCoreMetricManager().registerMetricProducer(this, 
Attributes.empty());
   }
 
   public static final String METRIC_SCOPE = "peerSync";
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateLog.java 
b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
index d9ea1d24efd..d2d50927b8e 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateLog.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
@@ -453,8 +453,7 @@ public class UpdateLog implements PluginInfoInitialized, 
SolrMetricProducer {
             getTlogDir(),
             id);
       }
-      core.getCoreMetricManager()
-          .registerMetricProducer(SolrInfoBean.Category.TLOG.toString(), this);
+      core.getCoreMetricManager().registerMetricProducer(this, 
Attributes.empty());
 
       String reResolved = resolveDataDir(core);
       if (dataDir == null || !dataDir.equals(reResolved)) {
@@ -500,7 +499,7 @@ public class UpdateLog implements PluginInfoInitialized, 
SolrMetricProducer {
         trackDeleteByQuery(q, version);
       }
     }
-    
core.getCoreMetricManager().registerMetricProducer(SolrInfoBean.Category.TLOG.toString(),
 this);
+    core.getCoreMetricManager().registerMetricProducer(this, 
Attributes.empty());
   }
 
   protected final void maybeClearLog(SolrCore core) {
diff --git a/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java 
b/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
index 03a07770b0f..c332f264486 100644
--- a/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
+++ b/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
@@ -16,9 +16,7 @@
  */
 package org.apache.solr.core;
 
-import com.codahale.metrics.Gauge;
 import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.request.SolrRequestHandler;
 import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.BeforeClass;
@@ -32,12 +30,14 @@ public class RequestHandlersTest extends SolrTestCaseJ4 {
 
   @Test
   public void testInitCount() {
-    String registry = h.getCore().getCoreMetricManager().getRegistryName();
-    SolrMetricManager manager = h.getCoreContainer().getMetricManager();
-    @SuppressWarnings({"unchecked"})
-    Gauge<Number> g =
-        (Gauge<Number>) 
manager.registry(registry).getMetrics().get("QUERY./mock.initCount");
-    assertEquals("Incorrect init count", 1, g.getValue().intValue());
+    var datapoint =
+        SolrMetricTestUtils.getGaugeDatapoint(
+            h.getCore(),
+            "mock_request",
+            SolrMetricTestUtils.newStandaloneLabelsBuilder(h.getCore())
+                .label("handler", "/mock")
+                .build());
+    assertEquals(1.0, datapoint.getValue(), 0.0);
   }
 
   @Test
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/StatsReloadRaceTest.java 
b/solr/core/src/test/org/apache/solr/handler/admin/StatsReloadRaceTest.java
index 7f88b6c8d5c..641a6c66ed3 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/StatsReloadRaceTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/StatsReloadRaceTest.java
@@ -18,11 +18,13 @@ package org.apache.solr.handler.admin;
 
 import java.util.List;
 import java.util.Random;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.solr.common.params.CoreAdminParams.CoreAdminAction;
+import org.apache.solr.common.util.RetryUtil;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.util.SolrMetricTestUtils;
@@ -54,7 +56,6 @@ public class StatsReloadRaceTest extends SolrTestCaseJ4 {
     for (int i = 0; i < atLeast(random, 2); i++) {
 
       int asyncId = taskNum.incrementAndGet();
-
       h.getCoreContainer()
           .getMultiCoreHandler()
           .handleRequest(
@@ -68,18 +69,19 @@ public class StatsReloadRaceTest extends SolrTestCaseJ4 {
                   "async",
                   "" + asyncId),
               new SolrQueryResponse());
-
-      boolean isCompleted;
-      do {
-        if (random.nextBoolean()) {
-          requestMetrics(true);
-        } else {
-          requestCoreStatus();
-        }
-
-        isCompleted = checkReloadCompletion(asyncId);
-      } while (!isCompleted);
-      requestMetrics(false);
+      try (SolrCore core = h.getCoreInc()) {
+        boolean isCompleted;
+        do {
+          if (random.nextBoolean()) {
+            requestMetrics(core, true);
+          } else {
+            requestCoreStatus();
+          }
+
+          isCompleted = checkReloadCompletion(asyncId);
+        } while (!isCompleted);
+        requestMetrics(core, false);
+      }
     }
   }
 
@@ -120,34 +122,40 @@ public class StatsReloadRaceTest extends SolrTestCaseJ4 {
     return isCompleted;
   }
 
-  private void requestMetrics(boolean softFail) throws Exception {
-    SolrQueryResponse rsp = new SolrQueryResponse();
-    String registry = "solr.core." + h.coreName;
-    String key = "SEARCHER.searcher.indexVersion";
-    boolean found = false;
-    int count = 10;
-    while (!found && count-- > 0) {
+  private void requestMetrics(SolrCore core, boolean softFail) throws 
Exception {
+    try {
       // this is not guaranteed to exist right away after core reload - 
there's a
       // small window between core load and before searcher metrics are 
registered,
       // so we may have to check a few times, and then fail softly if reload 
is not complete yet
-      SolrCore core = h.getCore();
-      var indexVersion =
-          SolrMetricTestUtils.getGaugeDatapoint(
-              core,
-              "solr_searcher_index_version",
-              SolrMetricTestUtils.newStandaloneLabelsBuilder(core)
-                  .label("category", "SEARCHER")
-                  .build());
-      if (indexVersion == null) {
-        Thread.sleep(500);
-      } else {
-        found = true;
-        break;
+      RetryUtil.retryUntil(
+          "solr_searcher_index_version metric not found",
+          10,
+          500,
+          TimeUnit.MILLISECONDS,
+          () -> {
+            var reader =
+                core.getSolrMetricsContext()
+                    .getMetricManager()
+                    
.getPrometheusMetricReader(core.getSolrMetricsContext().getRegistryName());
+            if (reader == null) {
+              return false;
+            }
+
+            var datapoint =
+                SolrMetricTestUtils.getGaugeDatapoint(
+                    reader,
+                    "solr_searcher_index_version",
+                    SolrMetricTestUtils.newStandaloneLabelsBuilder(core)
+                        .label("category", "SEARCHER")
+                        .build());
+
+            return datapoint != null;
+          });
+    } catch (Exception e) {
+      if (softFail) {
+        return;
       }
+      throw e;
     }
-    if (softFail && !found) {
-      return;
-    }
-    assertTrue("solr_searcher_index_version metric not found", found);
   }
 }
diff --git 
a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java 
b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
index b49f2fbe471..49f8421b86e 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
@@ -79,7 +79,7 @@ public class SolrCoreMetricManagerTest extends SolrTestCaseJ4 
{
     Map<String, Counter> metrics = 
SolrMetricTestUtils.getRandomMetrics(random);
     SolrMetricProducer producer = SolrMetricTestUtils.getProducerOf(category, 
scope, metrics);
     try {
-      coreMetricManager.registerMetricProducer(scope, producer);
+      coreMetricManager.registerMetricProducer(producer, Attributes.empty());
       assertNotNull(scope);
       assertNotNull(category);
       assertRegistered(scope, metrics, coreMetricManager);
@@ -91,28 +91,6 @@ public class SolrCoreMetricManagerTest extends 
SolrTestCaseJ4 {
     }
   }
 
-  @Test
-  public void testRegisterMetricsWithReplacements() {
-    Random random = random();
-
-    Map<String, Counter> registered = new HashMap<>();
-    String scope = SolrMetricTestUtils.getRandomScope(random, true);
-    SolrInfoBean.Category category = 
SolrMetricTestUtils.getRandomCategory(random, true);
-
-    int iterations = TestUtil.nextInt(random, 0, MAX_ITERATIONS);
-    for (int i = 0; i < iterations; ++i) {
-      Map<String, Counter> metrics =
-          SolrMetricTestUtils.getRandomMetricsWithReplacements(random, 
registered);
-      if (metrics.isEmpty()) {
-        continue;
-      }
-      SolrMetricProducer producer = 
SolrMetricTestUtils.getProducerOf(category, scope, metrics);
-      coreMetricManager.registerMetricProducer(scope, producer);
-      registered.putAll(metrics);
-      assertRegistered(scope, registered, coreMetricManager);
-    }
-  }
-
   @Test
   public void testLoadReporter() throws Exception {
     Random random = random();
@@ -189,8 +167,7 @@ public class SolrCoreMetricManagerTest extends 
SolrTestCaseJ4 {
     Map<String, Long> initialMetrics =
         SolrMetricTestUtils.getRandomPrometheusMetricsWithReplacements(random, 
new HashMap<>());
     var initialProducer = new 
SolrMetricTestUtils.TestSolrMetricProducer(coreName, initialMetrics);
-    coreMetricManager.registerMetricProducer(
-        SolrMetricTestUtils.getRandomScope(random, true), initialProducer);
+    coreMetricManager.registerMetricProducer(initialProducer, 
Attributes.empty());
 
     var labels = 
SolrMetricTestUtils.newStandaloneLabelsBuilder(h.getCore()).build();
 
diff --git 
a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java 
b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
index d829575961e..23b39040695 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
@@ -17,17 +17,14 @@
 
 package org.apache.solr.metrics;
 
-import static org.apache.solr.metrics.SolrMetricProducer.TYPE_ATTR;
-
-import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
+import io.opentelemetry.exporter.prometheus.PrometheusMetricReader;
 import 
io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot;
-import io.prometheus.metrics.model.snapshots.MetricSnapshots;
+import io.prometheus.metrics.model.snapshots.Labels;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
 import org.apache.http.client.HttpClient;
 import org.apache.solr.SolrTestCaseJ4;
@@ -84,38 +81,22 @@ public class SolrMetricsIntegrationTest extends 
SolrTestCaseJ4 {
 
   @Test
   public void testCoreContainerMetrics() {
-    MetricSnapshots metrics =
-        new MetricSnapshots(
-             metricManager.getPrometheusMetricReaders().entrySet().stream()
-                .flatMap(
-                    entry ->
-                        entry.getValue().collect().stream()
-                            .filter(m -> 
!m.getMetadata().getPrometheusName().startsWith("target")))
-                .toList());
-
-    GaugeSnapshot coresLoaded =
-        SolrMetricTestUtils.getMetricSnapshot(GaugeSnapshot.class, metrics, 
"solr_cores_loaded");
-    assertTrue(getGaugeOpt(coresLoaded, "permanent").isPresent());
-    assertTrue(getGaugeOpt(coresLoaded, "transient").isPresent());
-    assertTrue(getGaugeOpt(coresLoaded, "unloaded").isPresent());
-
-    GaugeSnapshot fsDiskSpace =
-        SolrMetricTestUtils.getMetricSnapshot(
-            GaugeSnapshot.class, metrics, 
"solr_cores_filesystem_disk_space_bytes");
-    assertTrue(getGaugeOpt(fsDiskSpace, "total_space").isPresent());
-    assertTrue(getGaugeOpt(fsDiskSpace, "usable_space").isPresent());
-
-    GaugeSnapshot rootDiskSpace =
-        SolrMetricTestUtils.getMetricSnapshot(
-            GaugeSnapshot.class, metrics, "solr_cores_root_disk_space_bytes");
-    assertTrue(getGaugeOpt(rootDiskSpace, "total_space").isPresent());
-    assertTrue(getGaugeOpt(rootDiskSpace, "usable_space").isPresent());
+    var reader = metricManager.getPrometheusMetricReader("solr.node");
+
+    assertNotNull(getGaugeOpt(reader, "solr_cores_loaded", "permanent"));
+    assertNotNull(getGaugeOpt(reader, "solr_cores_loaded", "transient"));
+    assertNotNull(getGaugeOpt(reader, "solr_cores_loaded", "unloaded"));
+
+    assertNotNull(getGaugeOpt(reader, "solr_disk_space_bytes", "total_space"));
+    assertNotNull(getGaugeOpt(reader, "solr_disk_space_bytes", 
"usable_space"));
   }
 
-  private static Optional<GaugeDataPointSnapshot> getGaugeOpt(GaugeSnapshot 
gauges, String type) {
-    return gauges.getDataPoints().stream()
-        .filter(g -> g.getLabels().get(TYPE_ATTR.toString()).equals(type))
-        .findFirst();
+  private static GaugeDataPointSnapshot getGaugeOpt(
+      PrometheusMetricReader reader, String metricName, String type) {
+    return SolrMetricTestUtils.getGaugeDatapoint(
+        reader,
+        metricName,
+        Labels.of("category", "CONTAINER", "otel_scope_name", 
"org.apache.solr", "type", type));
   }
 
   // NOCOMMIT: Comeback and fix this test after merging the SolrZKClient 
metrics migration
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrCachePerf.java 
b/solr/core/src/test/org/apache/solr/search/TestSolrCachePerf.java
index 0675e43e752..ff676ef4956 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrCachePerf.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrCachePerf.java
@@ -33,7 +33,6 @@ import 
org.apache.commons.math3.stat.descriptive.SummaryStatistics;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.metrics.SolrMetricsContext;
-import org.apache.solr.metrics.otel.NoopMetricExporter;
 import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.Before;
 import org.junit.Test;
@@ -103,7 +102,7 @@ public class TestSolrCachePerf extends SolrTestCaseJ4 {
       boolean useCompute)
       throws Exception {
     for (Class<? extends SolrCache> clazz : IMPLS) {
-      SolrMetricManager metricManager = new SolrMetricManager(new 
NoopMetricExporter());
+      SolrMetricManager metricManager = new SolrMetricManager(null);
       @SuppressWarnings({"unchecked"})
       SolrCache<String, String> cache = 
clazz.getDeclaredConstructor().newInstance();
       Map<String, String> params = new HashMap<>();
diff --git 
a/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtlpExporterFactory.java
 
b/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtlpExporterFactory.java
index 879aecd99b8..8237596be42 100644
--- 
a/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtlpExporterFactory.java
+++ 
b/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtlpExporterFactory.java
@@ -21,7 +21,6 @@ import 
io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
 import io.opentelemetry.sdk.metrics.export.MetricExporter;
 import java.lang.invoke.MethodHandles;
 import org.apache.solr.metrics.otel.MetricExporterFactory;
-import org.apache.solr.metrics.otel.NoopMetricExporter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,7 +29,6 @@ import org.slf4j.LoggerFactory;
  *
  * @see io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter
  * @see io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter
- * @see NoopMetricExporter
  */
 public class OtlpExporterFactory implements MetricExporterFactory {
 
@@ -39,18 +37,17 @@ public class OtlpExporterFactory implements 
MetricExporterFactory {
   public MetricExporter getExporter() {
     if (!OTLP_EXPORTER_ENABLED) {
       log.info("OTLP metric exporter is disabled.");
-      return new NoopMetricExporter();
+      return null;
     }
 
     return switch (OTLP_EXPORTER_PROTOCOL) {
       case "grpc" -> OtlpGrpcMetricExporter.getDefault();
       case "http" -> OtlpHttpMetricExporter.getDefault();
-      case "none" -> new NoopMetricExporter();
+      case "none" -> null;
       default -> {
         log.warn(
-            "Unknown OTLP exporter type: {}. Defaulting to NO-OP exporter.",
-            OTLP_EXPORTER_PROTOCOL);
-        yield new NoopMetricExporter();
+            "Unknown OTLP exporter type: {}. Disabling metric exporter", 
OTLP_EXPORTER_PROTOCOL);
+        yield null;
       }
     };
   }
diff --git a/solr/server/etc/security.policy b/solr/server/etc/security.policy
index 2e65fc70e07..44514befe56 100644
--- a/solr/server/etc/security.policy
+++ b/solr/server/etc/security.policy
@@ -132,7 +132,7 @@ grant {
   permission javax.management.MBeanServerPermission "releaseMBeanServer";
   permission javax.management.MBeanTrustPermission "register";
 
-  
+
   // needed by crossdc
   permission javax.security.auth.AuthPermission "getLoginConfiguration";
   permission javax.security.auth.AuthPermission "setLoginConfiguration";
@@ -218,3 +218,7 @@ grant {
   // expanded to a wildcard if set, allows all networking everywhere
   permission java.net.SocketPermission "${solr.internal.network.permission}", 
"accept,listen,connect,resolve";
 };
+
+grant {
+    permission jdk.jfr.FlightRecorderPermission "accessFlightRecorder";
+};
diff --git 
a/solr/test-framework/src/java/org/apache/solr/core/MockQuerySenderListenerReqHandler.java
 
b/solr/test-framework/src/java/org/apache/solr/core/MockQuerySenderListenerReqHandler.java
index 622a0c25a14..7a2812e4862 100644
--- 
a/solr/test-framework/src/java/org/apache/solr/core/MockQuerySenderListenerReqHandler.java
+++ 
b/solr/test-framework/src/java/org/apache/solr/core/MockQuerySenderListenerReqHandler.java
@@ -42,8 +42,12 @@ public class MockQuerySenderListenerReqHandler extends 
RequestHandlerBase {
   public void initializeMetrics(
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
     super.initializeMetrics(parentContext, attributes, scope);
-    solrMetricsContext.gauge(
-        () -> initCounter.intValue(), true, "initCount", 
getCategory().toString(), scope);
+    solrMetricsContext.observableLongGauge(
+        "mock_request",
+        "mock",
+        (observableLongMeasurement) -> {
+          observableLongMeasurement.record(initCounter.intValue(), attributes);
+        });
   }
 
   @Override

Reply via email to