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

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


The following commit(s) were added to refs/heads/feature/SOLR-17458 by this 
push:
     new 845700d6a71 SOLR-17806: Migrate CaffeineCache to OTEL (#3671)
845700d6a71 is described below

commit 845700d6a711d10db41de5bcc74036023b9d7b57
Author: Matthew Biscocho <[email protected]>
AuthorDate: Fri Sep 26 11:09:57 2025 -0400

    SOLR-17806: Migrate CaffeineCache to OTEL (#3671)
    
    * Migrate base metrics to OTEL
    
    * Fix broken tests
    
    * Cleanup utility methods
    
    * Clean up more tests
    
    * Change ram used bytes name
    
    * Change based on feedback
    
    * Address feedback
    
    * Make cumulative cache metrics the default
    
    * Minor feedback
    
    * Pass in metric name for caffeine cache
    
    ---------
    
    Co-authored-by: Matthew Biscocho <[email protected]>
---
 .../java/org/apache/solr/blockcache/Metrics.java   |   9 +-
 .../java/org/apache/solr/core/CoreContainer.java   |  10 +-
 .../src/java/org/apache/solr/core/SolrCore.java    |  35 +++--
 .../apache/solr/handler/ReplicationHandler.java    |  23 ++--
 .../apache/solr/metrics/SolrCoreMetricManager.java |  20 +--
 .../org/apache/solr/metrics/SolrMetricManager.java |  39 +++++-
 .../apache/solr/metrics/SolrMetricProducer.java    |   2 +
 .../apache/solr/metrics/SolrMetricsContext.java    |  35 +++--
 .../java/org/apache/solr/search/CaffeineCache.java | 117 +++++++++-------
 .../org/apache/solr/search/SolrFieldCacheBean.java |   4 +-
 .../org/apache/solr/search/SolrIndexSearcher.java  |   6 +-
 .../org/apache/solr/update/SolrIndexWriter.java    |  21 +--
 .../src/test/org/apache/solr/CursorPagingTest.java |  63 +++++----
 .../apache/solr/core/TestSolrConfigHandler.java    |  38 +++---
 .../test/org/apache/solr/core/TimeAllowedTest.java |  92 ++++++-------
 .../org/apache/solr/search/TestCaffeineCache.java  | 129 ++++++++++++------
 .../solr/search/TestFiltersQueryCaching.java       |  56 +++-----
 .../apache/solr/search/TestMainQueryCaching.java   |  20 +--
 .../solr/search/TestReRankQParserPlugin.java       |  35 +++--
 .../org/apache/solr/search/TestSolr4Spatial2.java  |  49 ++++---
 .../org/apache/solr/search/TestSolrCachePerf.java  |  25 +++-
 .../apache/solr/search/TestSolrQueryParser.java    | 114 ++++++++--------
 .../test/org/apache/solr/search/TestThinCache.java |  82 ++++++++----
 .../org/apache/solr/search/join/BJQParserTest.java |  66 +++++----
 .../solr/search/join/TestNestedDocsSort.java       |  22 ++-
 .../solr/search/join/TestScoreJoinQPScore.java     | 147 +++++++++++++++------
 .../org/apache/solr/util/SolrMetricTestUtils.java  |  52 ++++++++
 27 files changed, 778 insertions(+), 533 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/blockcache/Metrics.java 
b/solr/core/src/java/org/apache/solr/blockcache/Metrics.java
index 98c9b2dbef6..4de589a1103 100644
--- a/solr/core/src/java/org/apache/solr/blockcache/Metrics.java
+++ b/solr/core/src/java/org/apache/solr/blockcache/Metrics.java
@@ -60,14 +60,15 @@ public class Metrics extends SolrCacheBase implements 
SolrInfoBean {
     var baseAttributes =
         attributes.toBuilder().put(CATEGORY_ATTR, 
getCategory().toString()).build();
     var blockcacheStats =
-        solrMetricsContext.longMeasurement("solr_block_cache_stats", "Block 
cache stats");
+        solrMetricsContext.longGaugeMeasurement("solr_block_cache_stats", 
"Block cache stats");
     var hitRatio =
-        solrMetricsContext.doubleMeasurement("solr_block_cache_hit_ratio", 
"Block cache hit ratio");
+        solrMetricsContext.doubleGaugeMeasurement(
+            "solr_block_cache_hit_ratio", "Block cache hit ratio");
     var perSecStats =
-        solrMetricsContext.doubleMeasurement(
+        solrMetricsContext.doubleGaugeMeasurement(
             "solr_block_cache_stats_per_second", "Block cache per second 
stats");
     var bufferCacheStats =
-        solrMetricsContext.doubleMeasurement(
+        solrMetricsContext.doubleGaugeMeasurement(
             "solr_buffer_cache_stats", "Buffer cache per second stats");
 
     this.toClose =
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java 
b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 8a322cc8cbd..97ee8666184 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -28,6 +28,7 @@ import static 
org.apache.solr.common.params.CommonParams.ZK_PATH;
 import static org.apache.solr.common.params.CommonParams.ZK_STATUS_PATH;
 import static org.apache.solr.metrics.SolrMetricProducer.CATEGORY_ATTR;
 import static org.apache.solr.metrics.SolrMetricProducer.HANDLER_ATTR;
+import static org.apache.solr.metrics.SolrMetricProducer.NAME_ATTR;
 import static 
org.apache.solr.search.SolrIndexSearcher.EXECUTOR_MAX_CPU_THREADS;
 import static 
org.apache.solr.security.AuthenticationPlugin.AUTHENTICATION_PLUGIN_PROP;
 
@@ -146,6 +147,7 @@ import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestHandler;
 import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.search.CacheConfig;
+import org.apache.solr.search.CaffeineCache;
 import org.apache.solr.search.SolrCache;
 import org.apache.solr.search.SolrFieldCacheBean;
 import org.apache.solr.search.SolrIndexSearcher;
@@ -871,8 +873,12 @@ public class CoreContainer {
       for (Map.Entry<String, CacheConfig> e : cachesConfig.entrySet()) {
         SolrCache<?, ?> c = e.getValue().newInstance();
         String cacheName = e.getKey();
-        // NOCOMMIT SOLR-17458: Add Otel
-        c.initializeMetrics(solrMetricsContext, Attributes.empty(), 
"nodeLevelCache/" + cacheName);
+        if (c instanceof CaffeineCache<?, ?> caffeineCache) {
+          caffeineCache.initializeMetrics(
+              solrMetricsContext,
+              Attributes.builder().put(NAME_ATTR, cacheName).build(),
+              "solr_node_cache");
+        }
         m.put(cacheName, c);
       }
       this.caches = Collections.unmodifiableMap(m);
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 c62563a2209..09e2747d7a6 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -21,6 +21,7 @@ import static 
org.apache.solr.handler.admin.MetricsHandler.OPEN_METRICS_WT;
 import static 
org.apache.solr.handler.admin.MetricsHandler.PROMETHEUS_METRICS_WT;
 import static org.apache.solr.metrics.SolrCoreMetricManager.COLLECTION_ATTR;
 import static org.apache.solr.metrics.SolrCoreMetricManager.CORE_ATTR;
+import static org.apache.solr.metrics.SolrCoreMetricManager.REPLICA_ATTR;
 import static org.apache.solr.metrics.SolrCoreMetricManager.SHARD_ATTR;
 
 import com.github.benmanes.caffeine.cache.Cache;
@@ -259,7 +260,7 @@ public class SolrCore implements SolrInfoBean, Closeable {
 
   private volatile boolean newSearcherReady = false;
 
-  private final Attributes coreAttributes;
+  private Attributes coreAttributes;
   private AttributedLongCounter newSearcherCounter;
   private AttributedLongCounter newSearcherMaxReachedCounter;
   private AttributedLongCounter newSearcherOtherErrorsCounter;
@@ -556,6 +557,25 @@ public class SolrCore implements SolrInfoBean, Closeable {
     assert this.name != null;
     assert coreDescriptor.getCloudDescriptor() == null : "Cores are not 
renamed in SolrCloud";
     this.name = Objects.requireNonNull(v);
+    initCoreAttributes();
+  }
+
+  public Attributes getCoreAttributes() {
+    return coreAttributes;
+  }
+
+  private void initCoreAttributes() {
+    this.coreAttributes =
+        (coreContainer.isZooKeeperAware())
+            ? Attributes.builder()
+                .put(COLLECTION_ATTR, coreDescriptor.getCollectionName())
+                .put(CORE_ATTR, getName())
+                .put(SHARD_ATTR, 
coreDescriptor.getCloudDescriptor().getShardId())
+                .put(
+                    REPLICA_ATTR,
+                    
Utils.parseMetricsReplicaName(coreDescriptor.getCollectionName(), getName()))
+                .build()
+            : Attributes.builder().put(CORE_ATTR, getName()).build();
   }
 
   /**
@@ -1089,17 +1109,6 @@ public class SolrCore implements SolrInfoBean, Closeable 
{
       this.solrMetricsContext = coreMetricManager.getSolrMetricsContext();
       this.coreMetricManager.loadReporters();
 
-      if (coreContainer.isZooKeeperAware()) {
-        this.coreAttributes =
-            Attributes.builder()
-                .put(COLLECTION_ATTR, coreDescriptor.getCollectionName())
-                .put(CORE_ATTR, coreDescriptor.getName())
-                .put(SHARD_ATTR, 
coreDescriptor.getCloudDescriptor().getShardId())
-                .build();
-      } else {
-        this.coreAttributes = Attributes.builder().put(CORE_ATTR, 
coreDescriptor.getName()).build();
-      }
-
       if (updateHandler == null) {
         directoryFactory = initDirectoryFactory();
         recoveryStrategyBuilder = initRecoveryStrategyBuilder();
@@ -1120,6 +1129,8 @@ public class SolrCore implements SolrInfoBean, Closeable {
       checkVersionFieldExistsInSchema(schema, coreDescriptor);
       setLatestSchema(schema);
 
+      initCoreAttributes();
+
       // initialize core metrics
       initializeMetrics(solrMetricsContext, coreAttributes, "");
 
diff --git a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java 
b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
index b900dc22ddb..010d1090e48 100644
--- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
@@ -841,7 +841,6 @@ public class ReplicationHandler extends RequestHandlerBase
     }
   }
 
-  // NOCOMMIT SOLR-17458: Update with OTEL
   @Override
   public void initializeMetrics(
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
@@ -853,51 +852,51 @@ public class ReplicationHandler extends RequestHandlerBase
     super.initializeMetrics(parentContext, replicationAttributes, scope);
 
     ObservableLongMeasurement indexSizeMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_index_size", "Size of the index in bytes", 
OtelUnit.BYTES);
 
     ObservableLongMeasurement indexVersionMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_index_version", "Current index version");
 
     ObservableLongMeasurement indexGenerationMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_index_generation", "Current index generation");
 
     ObservableLongMeasurement isLeaderMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_is_leader", "Whether this node is a leader (1) 
or not (0)");
 
     ObservableLongMeasurement isFollowerMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_is_follower", "Whether this node is a follower 
(1) or not (0)");
 
     ObservableLongMeasurement replicationEnabledMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_is_enabled", "Whether replication is enabled (1) 
or not (0)");
 
     ObservableLongMeasurement isPollingDisabledMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_is_polling_disabled", "Whether polling is 
disabled (1) or not (0)");
 
     ObservableLongMeasurement isReplicatingMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_is_replicating", "Whether replication is in 
progress (1) or not (0)");
 
     ObservableLongMeasurement timeElapsedMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_time_elapsed",
             "Time elapsed during replication in seconds",
             OtelUnit.SECONDS);
 
     ObservableLongMeasurement bytesDownloadedMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_downloaded_size",
             "Total bytes downloaded during replication",
             OtelUnit.BYTES);
 
     ObservableLongMeasurement downloadSpeedMetric =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_replication_download_speed", "Download speed in bytes per 
second");
 
     metricsCallback =
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 6af631d6ebf..86c81c83bd8 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
@@ -20,7 +20,6 @@ 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;
@@ -128,19 +127,11 @@ public class SolrCoreMetricManager implements Closeable {
     // tracked producers.
     // There is some possible improvement that can be done here to not have to 
duplicate code in
     // registerMetricProducer
-    var attributes =
-        Attributes.builder()
-            .put(CORE_ATTR, core.getName())
-            .put(COLLECTION_ATTR, collectionName)
-            .put(SHARD_ATTR, shardName)
-            .put(REPLICA_ATTR, replicaName)
-            .build();
-
-    core.initializeMetrics(solrMetricsContext, attributes, core.getName());
+    core.initializeMetrics(solrMetricsContext, core.getCoreAttributes(), 
core.getName());
 
     registeredProducers.forEach(
         metricProducer -> {
-          var producerAttributes = attributes.toBuilder();
+          var producerAttributes = core.getCoreAttributes().toBuilder();
           if (metricProducer.scope().startsWith("/"))
             producerAttributes.put(HANDLER_ATTR, metricProducer.scope);
           metricProducer.producer.initializeMetrics(
@@ -173,12 +164,7 @@ public class SolrCoreMetricManager implements Closeable {
     // reregisterCoreMetrics
     // There is some possible improvement that can be done here to not have to 
duplicate code in
     // reregisterCoreMetrics
-    var attributesBuilder =
-        Attributes.builder()
-            .put(CORE_ATTR, core.getName())
-            .put(COLLECTION_ATTR, collectionName)
-            .put(SHARD_ATTR, shardName)
-            .put(REPLICA_ATTR, replicaName);
+    var attributesBuilder = core.getCoreAttributes().toBuilder();
     if (scope.startsWith("/")) attributesBuilder.put(HANDLER_ATTR, scope);
     producer.initializeMetrics(solrMetricsContext, attributesBuilder.build(), 
scope);
   }
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 98d18cea32f..b4e1e708d86 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
@@ -389,16 +389,26 @@ public class SolrMetricManager {
         .batchCallback(callback, measurement, additionalMeasurements);
   }
 
-  ObservableLongMeasurement longMeasurement(
+  ObservableLongMeasurement longGaugeMeasurement(
       String registry, String gaugeName, String description, OtelUnit unit) {
     return longGaugeBuilder(registry, gaugeName, description, 
unit).buildObserver();
   }
 
-  ObservableDoubleMeasurement doubleMeasurement(
+  ObservableDoubleMeasurement doubleGaugeMeasurement(
       String registry, String gaugeName, String description, OtelUnit unit) {
     return doubleGaugeBuilder(registry, gaugeName, description, 
unit).buildObserver();
   }
 
+  ObservableLongMeasurement longCounterMeasurement(
+      String registry, String counterName, String description, OtelUnit unit) {
+    return longCounterBuilder(registry, counterName, description, 
unit).buildObserver();
+  }
+
+  ObservableDoubleMeasurement doubleCounterMeasurement(
+      String registry, String counterName, String description, OtelUnit unit) {
+    return doubleCounterBuilder(registry, counterName, description, 
unit).buildObserver();
+  }
+
   private LongGaugeBuilder longGaugeBuilder(
       String registry, String gaugeName, String description, OtelUnit unit) {
     LongGaugeBuilder builder =
@@ -424,6 +434,31 @@ public class SolrMetricManager {
     return builder;
   }
 
+  private LongCounterBuilder longCounterBuilder(
+      String registry, String counterName, String description, OtelUnit unit) {
+    LongCounterBuilder builder =
+        meterProvider(registry)
+            .get(OTEL_SCOPE_NAME)
+            .counterBuilder(counterName)
+            .setDescription(description);
+    if (unit != null) builder.setUnit(unit.getSymbol());
+
+    return builder;
+  }
+
+  private DoubleCounterBuilder doubleCounterBuilder(
+      String registry, String counterName, String description, OtelUnit unit) {
+    DoubleCounterBuilder builder =
+        meterProvider(registry)
+            .get(OTEL_SCOPE_NAME)
+            .counterBuilder(counterName)
+            .setDescription(description)
+            .ofDoubles();
+    if (unit != null) builder.setUnit(unit.getSymbol());
+
+    return builder;
+  }
+
   // for unit tests
   public MetricRegistry.MetricSupplier<Counter> getCounterSupplier() {
     return counterSupplier;
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java 
b/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
index 435b7c0051c..ea046b8fda5 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
@@ -27,6 +27,8 @@ public interface SolrMetricProducer extends AutoCloseable {
   public static final AttributeKey<String> CATEGORY_ATTR = 
AttributeKey.stringKey("category");
   public static final AttributeKey<String> HANDLER_ATTR = 
AttributeKey.stringKey("handler");
   public static final AttributeKey<String> OPERATION_ATTR = 
AttributeKey.stringKey("ops");
+  public static final AttributeKey<String> RESULT_ATTR = 
AttributeKey.stringKey("result");
+  public static final AttributeKey<String> NAME_ATTR = 
AttributeKey.stringKey("name");
   public static final AttributeKey<String> PLUGIN_NAME_ATTR = 
AttributeKey.stringKey("plugin_name");
 
   /**
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricsContext.java 
b/solr/core/src/java/org/apache/solr/metrics/SolrMetricsContext.java
index 696ace6aa0d..05df56eba88 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricsContext.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricsContext.java
@@ -276,22 +276,41 @@ public class SolrMetricsContext {
         registryName, metricName, description, callback, unit);
   }
 
-  public ObservableLongMeasurement longMeasurement(String metricName, String 
description) {
-    return longMeasurement(metricName, description, null);
+  public ObservableLongMeasurement longGaugeMeasurement(String metricName, 
String description) {
+    return longGaugeMeasurement(metricName, description, null);
   }
 
-  public ObservableLongMeasurement longMeasurement(
+  public ObservableLongMeasurement longGaugeMeasurement(
       String metricName, String description, OtelUnit unit) {
-    return metricManager.longMeasurement(registryName, metricName, 
description, unit);
+    return metricManager.longGaugeMeasurement(registryName, metricName, 
description, unit);
   }
 
-  public ObservableDoubleMeasurement doubleMeasurement(String metricName, 
String description) {
-    return doubleMeasurement(metricName, description, null);
+  public ObservableDoubleMeasurement doubleGaugeMeasurement(String metricName, 
String description) {
+    return doubleGaugeMeasurement(metricName, description, null);
   }
 
-  public ObservableDoubleMeasurement doubleMeasurement(
+  public ObservableDoubleMeasurement doubleGaugeMeasurement(
       String metricName, String description, OtelUnit unit) {
-    return metricManager.doubleMeasurement(registryName, metricName, 
description, unit);
+    return metricManager.doubleGaugeMeasurement(registryName, metricName, 
description, unit);
+  }
+
+  public ObservableLongMeasurement longCounterMeasurement(String metricName, 
String description) {
+    return longCounterMeasurement(metricName, description, null);
+  }
+
+  public ObservableLongMeasurement longCounterMeasurement(
+      String metricName, String description, OtelUnit unit) {
+    return metricManager.longCounterMeasurement(registryName, metricName, 
description, unit);
+  }
+
+  public ObservableDoubleMeasurement doubleCounterMeasurement(
+      String metricName, String description) {
+    return doubleCounterMeasurement(metricName, description, null);
+  }
+
+  public ObservableDoubleMeasurement doubleCounterMeasurement(
+      String metricName, String description, OtelUnit unit) {
+    return metricManager.doubleCounterMeasurement(registryName, metricName, 
description, unit);
   }
 
   public BatchCallback batchCallback(
diff --git a/solr/core/src/java/org/apache/solr/search/CaffeineCache.java 
b/solr/core/src/java/org/apache/solr/search/CaffeineCache.java
index 8251cd0be96..601bdf80e11 100644
--- a/solr/core/src/java/org/apache/solr/search/CaffeineCache.java
+++ b/solr/core/src/java/org/apache/solr/search/CaffeineCache.java
@@ -16,6 +16,10 @@
  */
 package org.apache.solr.search;
 
+import static org.apache.solr.metrics.SolrMetricProducer.CATEGORY_ATTR;
+import static org.apache.solr.metrics.SolrMetricProducer.OPERATION_ATTR;
+import static org.apache.solr.metrics.SolrMetricProducer.RESULT_ATTR;
+
 import com.github.benmanes.caffeine.cache.AsyncCache;
 import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
@@ -23,8 +27,8 @@ import com.github.benmanes.caffeine.cache.Policy.Eviction;
 import com.github.benmanes.caffeine.cache.RemovalCause;
 import com.github.benmanes.caffeine.cache.RemovalListener;
 import com.github.benmanes.caffeine.cache.stats.CacheStats;
-import com.google.common.annotations.VisibleForTesting;
 import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.ObservableLongMeasurement;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.lang.invoke.MethodHandles;
@@ -43,8 +47,9 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.LongAdder;
 import org.apache.lucene.util.Accountable;
 import org.apache.lucene.util.RamUsageEstimator;
-import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.metrics.SolrMetricsContext;
+import org.apache.solr.metrics.otel.OtelUnit;
 import org.apache.solr.util.IOFunction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -99,8 +104,8 @@ public class CaffeineCache<K, V> extends SolrCacheBase
   private boolean cleanupThread;
   private boolean async;
 
-  private MetricsMap cacheMap;
   private SolrMetricsContext solrMetricsContext;
+  private AutoCloseable toClose;
 
   private long initialRamBytes = 0;
   private final LongAdder ramBytes = new LongAdder();
@@ -325,13 +330,14 @@ public class CaffeineCache<K, V> extends SolrCacheBase
 
   @Override
   public void close() throws IOException {
-    SolrCache.super.close();
     cache.invalidateAll();
     cache.cleanUp();
     if (executor instanceof ExecutorService) {
       ((ExecutorService) executor).shutdownNow();
     }
     ramBytes.reset();
+    IOUtils.closeQuietly(toClose);
+    SolrCache.super.close();
   }
 
   @Override
@@ -458,12 +464,6 @@ public class CaffeineCache<K, V> extends SolrCacheBase
     return description;
   }
 
-  // for unit tests only
-  @VisibleForTesting
-  MetricsMap getMetricsMap() {
-    return cacheMap;
-  }
-
   @Override
   public SolrMetricsContext getSolrMetricsContext() {
     return solrMetricsContext;
@@ -471,47 +471,72 @@ public class CaffeineCache<K, V> extends SolrCacheBase
 
   @Override
   public String toString() {
-    return name() + (cacheMap != null ? cacheMap.getValue().toString() : "");
+    return name();
   }
 
-  // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
+      SolrMetricsContext parentContext, Attributes attributes, String 
metricName) {
+    Attributes cacheAttributes =
+        attributes.toBuilder().put(CATEGORY_ATTR, 
getCategory().toString()).build();
     solrMetricsContext = parentContext.getChildContext(this);
-    cacheMap =
-        new MetricsMap(
-            map -> {
-              if (cache != null) {
-                CacheStats stats = cache.stats();
-                long hitCount = stats.hitCount() + hits.sum();
-                long insertCount = inserts.sum();
-                long lookupCount = stats.requestCount() + lookups.sum();
-
-                map.put(LOOKUPS_PARAM, lookupCount);
-                map.put(HITS_PARAM, hitCount);
-                map.put(HIT_RATIO_PARAM, hitRate(hitCount, lookupCount));
-                map.put(INSERTS_PARAM, insertCount);
-                map.put(EVICTIONS_PARAM, stats.evictionCount());
-                map.put(SIZE_PARAM, cache.asMap().size());
-                map.put("warmupTime", warmupTime);
-                map.put(RAM_BYTES_USED_PARAM, ramBytesUsed());
-                map.put(MAX_RAM_MB_PARAM, getMaxRamMB());
-
-                CacheStats cumulativeStats = priorStats.plus(stats);
-                long cumLookups = priorLookups + lookupCount;
-                long cumHits = priorHits + hitCount;
-                map.put("cumulative_lookups", cumLookups);
-                map.put("cumulative_hits", cumHits);
-                map.put("cumulative_hitratio", hitRate(cumHits, cumLookups));
-                map.put("cumulative_inserts", priorInserts + insertCount);
-                map.put("cumulative_evictions", 
cumulativeStats.evictionCount());
-              }
-            });
-    solrMetricsContext.gauge(cacheMap, true, scope, getCategory().toString());
-  }
 
-  private static double hitRate(long hitCount, long lookupCount) {
-    return lookupCount == 0 ? 1.0 : (double) hitCount / lookupCount;
+    ObservableLongMeasurement cacheLookupsMetric =
+        solrMetricsContext.longCounterMeasurement(
+            metricName + "_lookups", "Number of cumulative cache lookup 
results (hits and misses)");
+
+    ObservableLongMeasurement cacheOperationMetric =
+        solrMetricsContext.longCounterMeasurement(
+            metricName + "_ops", "Number of cumulative cache operations 
(inserts and evictions)");
+
+    ObservableLongMeasurement sizeMetric =
+        solrMetricsContext.longGaugeMeasurement(
+            metricName + "_size", "Current number cache entries");
+
+    ObservableLongMeasurement ramBytesUsedMetric =
+        solrMetricsContext.longGaugeMeasurement(
+            metricName + "_ram_used", "RAM bytes used by cache", 
OtelUnit.BYTES);
+
+    ObservableLongMeasurement warmupTimeMetric =
+        solrMetricsContext.longGaugeMeasurement(
+            metricName + "_warmup_time", "Cache warmup time (most recent)", 
OtelUnit.MILLISECONDS);
+
+    this.toClose =
+        solrMetricsContext.batchCallback(
+            () -> {
+              if (cache == null) {
+                return;
+              }
+              CacheStats stats = cache.stats();
+              long hitCount = stats.hitCount() + hits.sum();
+              long lookupCount = stats.requestCount() + lookups.sum();
+              long insertCount = inserts.sum();
+
+              sizeMetric.record(cache.asMap().size(), cacheAttributes);
+              ramBytesUsedMetric.record(ramBytesUsed(), cacheAttributes);
+              warmupTimeMetric.record(warmupTime, cacheAttributes);
+
+              CacheStats cumulativeStats = priorStats.plus(stats);
+              long cumLookups = priorLookups + lookupCount;
+              long cumHits = priorHits + hitCount;
+
+              cacheLookupsMetric.record(
+                  cumHits, cacheAttributes.toBuilder().put(RESULT_ATTR, 
"hit").build());
+              cacheLookupsMetric.record(
+                  cumLookups - cumHits,
+                  cacheAttributes.toBuilder().put(RESULT_ATTR, 
"miss").build());
+
+              cacheOperationMetric.record(
+                  priorInserts + insertCount,
+                  cacheAttributes.toBuilder().put(OPERATION_ATTR, 
"inserts").build());
+              cacheOperationMetric.record(
+                  cumulativeStats.evictionCount(),
+                  cacheAttributes.toBuilder().put(OPERATION_ATTR, 
"evictions").build());
+            },
+            cacheLookupsMetric,
+            cacheOperationMetric,
+            sizeMetric,
+            ramBytesUsedMetric,
+            warmupTimeMetric);
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java 
b/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java
index a0dff1245d7..64f89e27d4b 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java
@@ -58,10 +58,10 @@ public class SolrFieldCacheBean implements SolrInfoBean {
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
     this.solrMetricsContext = parentContext;
     var solrCacheStats =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_field_cache_entries", "Number of field cache entries");
     var solrCacheSize =
-        solrMetricsContext.longMeasurement(
+        solrMetricsContext.longGaugeMeasurement(
             "solr_field_cache_size", "Size of field cache in bytes", 
OtelUnit.BYTES);
     this.toClose =
         solrMetricsContext.batchCallback(
diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java 
b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
index ce4374c1bb9..be9733682b7 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
@@ -106,7 +106,6 @@ import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.SolrInfoBean;
 import org.apache.solr.index.SlowCompositeReaderWrapper;
 import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.metrics.SolrMetricsContext;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestInfo;
@@ -603,10 +602,9 @@ public class SolrIndexSearcher extends IndexSearcher 
implements Closeable, SolrI
     this.solrMetricsContext = 
core.getSolrMetricsContext().getChildContext(this);
     for (SolrCache<?, ?> cache : cacheList) {
       cache.initializeMetrics(
-          // TODO SOLR-17458: Add Otel
           solrMetricsContext,
-          Attributes.empty(),
-          SolrMetricManager.mkName(cache.name(), STATISTICS_KEY));
+          core.getCoreAttributes().toBuilder().put(NAME_ATTR, 
cache.name()).build(),
+          "solr_searcher_cache");
     }
     // TODO SOLR-17458: Add Otel
     initializeMetrics(solrMetricsContext, Attributes.empty(), STATISTICS_KEY);
diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java 
b/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
index 7fd5e434d6f..75bd8ddc311 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
@@ -16,15 +16,10 @@
  */
 package org.apache.solr.update;
 
-import static org.apache.solr.metrics.SolrCoreMetricManager.COLLECTION_ATTR;
-import static org.apache.solr.metrics.SolrCoreMetricManager.CORE_ATTR;
-import static org.apache.solr.metrics.SolrCoreMetricManager.REPLICA_ATTR;
-import static org.apache.solr.metrics.SolrCoreMetricManager.SHARD_ATTR;
 import static org.apache.solr.metrics.SolrMetricProducer.CATEGORY_ATTR;
 import static org.apache.solr.metrics.SolrMetricProducer.TYPE_ATTR;
 
 import io.opentelemetry.api.common.AttributeKey;
-import io.opentelemetry.api.common.Attributes;
 import io.opentelemetry.api.metrics.ObservableLongGauge;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
@@ -44,7 +39,6 @@ import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.InfoStream;
 import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.common.util.SuppressForbidden;
-import org.apache.solr.common.util.Utils;
 import org.apache.solr.core.DirectoryFactory;
 import org.apache.solr.core.DirectoryFactory.DirContext;
 import org.apache.solr.core.SolrCore;
@@ -191,19 +185,10 @@ public class SolrIndexWriter extends IndexWriter {
       } else {
         mergeTotals = false;
       }
-      String coreName = core.getCoreDescriptor().getName();
-      var baseAttributesBuilder =
-          Attributes.builder()
+      var baseAttributes =
+          core.getCoreAttributes().toBuilder()
               .put(CATEGORY_ATTR, SolrInfoBean.Category.INDEX.toString())
-              .put(CORE_ATTR, coreName);
-      if (core.getCoreContainer().isZooKeeperAware()) {
-        String collectionName = core.getCoreDescriptor().getCollectionName();
-        baseAttributesBuilder
-            .put(COLLECTION_ATTR, collectionName)
-            .put(SHARD_ATTR, 
core.getCoreDescriptor().getCloudDescriptor().getShardId())
-            .put(REPLICA_ATTR, Utils.parseMetricsReplicaName(collectionName, 
coreName));
-      }
-      var baseAttributes = baseAttributesBuilder.build();
+              .build();
       if (mergeDetails) {
         mergeTotals = true; // override
         majorMergedDocs =
diff --git a/solr/core/src/test/org/apache/solr/CursorPagingTest.java 
b/solr/core/src/test/org/apache/solr/CursorPagingTest.java
index 45689e2cf21..0babb49496c 100644
--- a/solr/core/src/test/org/apache/solr/CursorPagingTest.java
+++ b/solr/core/src/test/org/apache/solr/CursorPagingTest.java
@@ -45,11 +45,11 @@ import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.CursorMarkParams;
 import org.apache.solr.common.params.GroupParams;
 import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.search.CursorMark;
 import org.apache.solr.util.LogLevel;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.After;
 import org.junit.BeforeClass;
 
@@ -715,30 +715,19 @@ public class CursorPagingTest extends SolrTestCaseJ4 {
 
     final Collection<String> allFieldNames = getAllSortFieldNames();
 
-    final MetricsMap filterCacheStats =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper)
-                    h.getCore()
-                        .getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.filterCache"))
-                .getGauge();
-    assertNotNull(filterCacheStats);
-    final MetricsMap queryCacheStats =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper)
-                    h.getCore()
-                        .getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.queryResultCache"))
-                .getGauge();
-    assertNotNull(queryCacheStats);
-
-    final long preQcIn = (Long) queryCacheStats.getValue().get("inserts");
-    final long preFcIn = (Long) filterCacheStats.getValue().get("inserts");
-    final long preFcHits = (Long) filterCacheStats.getValue().get("hits");
+    SolrCore solrCore = h.getCore();
+
+    // Get initial metrics for filter and query cache
+    var preFilterInserts =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(solrCore, 
SolrMetricTestUtils.FILTER_CACHE)
+            .getValue();
+    var preFilterHits =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(solrCore, 
SolrMetricTestUtils.FILTER_CACHE)
+            .getValue();
+    var preQueryInserts =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+                solrCore, SolrMetricTestUtils.QUERY_RESULT_CACHE)
+            .getValue();
 
     SentinelIntSet ids =
         assertFullWalkNoDups(
@@ -753,13 +742,21 @@ public class CursorPagingTest extends SolrTestCaseJ4 {
 
     assertEquals(6, ids.size());
 
-    final long postQcIn = (Long) queryCacheStats.getValue().get("inserts");
-    final long postFcIn = (Long) filterCacheStats.getValue().get("inserts");
-    final long postFcHits = (Long) filterCacheStats.getValue().get("hits");
-
-    assertEquals("query cache inserts changed", preQcIn, postQcIn);
-    assertEquals("filter cache did not grow correctly", 2, postFcIn - preFcIn);
-    assertTrue("filter cache did not have any new cache hits", 0 < postFcHits 
- preFcHits);
+    var postFilterInserts =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(solrCore, 
SolrMetricTestUtils.FILTER_CACHE)
+            .getValue();
+    var postFilterHits =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(solrCore, 
SolrMetricTestUtils.FILTER_CACHE)
+            .getValue();
+    var postQueryInserts =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+                solrCore, SolrMetricTestUtils.QUERY_RESULT_CACHE)
+            .getValue();
+
+    assertEquals("query cache inserts changed", preQueryInserts, 
postQueryInserts, 0.0);
+    assertEquals(
+        "filter cache did not grow correctly", 2, postFilterInserts - 
preFilterInserts, 0.0);
+    assertTrue("filter cache did not have any new cache hits", 0 < 
postFilterHits - preFilterHits);
   }
 
   /** randomized testing of a non-trivial number of docs using 
assertFullWalkNoDups */
diff --git a/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java 
b/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
index f9ff11a9ad8..927a40a47a8 100644
--- a/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
+++ b/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
@@ -1012,14 +1012,15 @@ public class TestSolrConfigHandler extends RestTestBase 
{
   public void testCacheDisableSolrConfig() throws Exception {
     RESTfulServerProvider oldProvider = restTestHarness.getServerProvider();
     restTestHarness.setServerProvider(() -> getBaseUrl());
-    MapWriter confMap = getRespMap("/admin/metrics", restTestHarness);
-    assertNotNull(
-        confMap._get(
-            asList("metrics", "solr.core.collection1", 
"CACHE.searcher.fieldValueCache"), null));
+    String prometheusMetrics = 
restTestHarness.query("/admin/metrics?wt=prometheus");
+    assertTrue(
+        "fieldValueCache metrics should be present",
+        prometheusMetrics.contains("name=\"fieldValueCache\""));
     // Here documentCache is disabled at initialization in SolrConfig
-    assertNull(
-        confMap._get(
-            asList("metrics", "solr.core.collection1", 
"CACHE.searcher.documentCache"), null));
+    assertFalse(
+        "documentCache metrics should be absent",
+        prometheusMetrics.contains("name=\"documentCache\""));
+
     restTestHarness.setServerProvider(oldProvider);
   }
 
@@ -1032,10 +1033,10 @@ public class TestSolrConfigHandler extends RestTestBase 
{
     assertEquals("399", 
overlay._getStr("overlay/props/query/documentCache/size"));
     // Setting size only will not enable the cache
     restTestHarness.setServerProvider(() -> getBaseUrl());
-    MapWriter confMap = getRespMap("/admin/metrics", restTestHarness);
-    assertNull(
-        confMap._get(
-            asList("metrics", "solr.core.collection1", 
"CACHE.searcher.documentCache"), null));
+
+    String prometheusMetrics = 
restTestHarness.query("/admin/metrics?wt=prometheus");
+    assertFalse(prometheusMetrics.contains("cache_name=\"documentCache\""));
+
     restTestHarness.setServerProvider(oldProvider);
   }
 
@@ -1045,20 +1046,19 @@ public class TestSolrConfigHandler extends RestTestBase 
{
     String payload = "{'set-property' : { 'query.documentCache.enabled': true} 
}";
     runConfigCommand(restTestHarness, "/config", payload);
     restTestHarness.setServerProvider(() -> getBaseUrl());
-    MapWriter confMap = getRespMap("/admin/metrics", restTestHarness);
-    assertNotNull(
-        confMap._get(
-            asList("metrics", "solr.core.collection1", 
"CACHE.searcher.documentCache"), null));
+
+    String prometheusMetrics = 
restTestHarness.query("/admin/metrics?wt=prometheus");
+    assertTrue(prometheusMetrics.contains("name=\"documentCache\""));
 
     // Disabling Cache
     payload = "{ 'set-property' : { 'query.documentCache.enabled': false } }";
     restTestHarness.setServerProvider(oldProvider);
+
     runConfigCommand(restTestHarness, "/config", payload);
     restTestHarness.setServerProvider(() -> getBaseUrl());
-    confMap = getRespMap("/admin/metrics", restTestHarness);
-    assertNull(
-        confMap._get(
-            asList("metrics", "solr.core.collection1", 
"CACHE.searcher.documentCache"), null));
+
+    prometheusMetrics = restTestHarness.query("/admin/metrics?wt=prometheus");
+    assertFalse(prometheusMetrics.contains("name=\"documentCache\""));
 
     restTestHarness.setServerProvider(oldProvider);
   }
diff --git a/solr/core/src/test/org/apache/solr/core/TimeAllowedTest.java 
b/solr/core/src/test/org/apache/solr/core/TimeAllowedTest.java
index 32521802d13..7a88a470a90 100644
--- a/solr/core/src/test/org/apache/solr/core/TimeAllowedTest.java
+++ b/solr/core/src/test/org/apache/solr/core/TimeAllowedTest.java
@@ -18,11 +18,11 @@ package org.apache.solr.core;
 
 import static org.apache.solr.common.util.Utils.fromJSONString;
 
+import io.prometheus.metrics.model.snapshots.CounterSnapshot;
 import java.util.Map;
 import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -110,25 +110,15 @@ public class TimeAllowedTest extends SolrTestCaseJ4 {
   public void testCacheAssumptions() throws Exception {
     String fq = "name:d*";
     SolrCore core = h.getCore();
-    MetricsMap filterCacheStats =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper<?>)
-                    core.getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.filterCache"))
-                .getGauge();
-    long fqInserts = (long) filterCacheStats.getValue().get("inserts");
-
-    MetricsMap queryCacheStats =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper<?>)
-                    core.getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.queryResultCache"))
-                .getGauge();
-    long qrInserts = (long) queryCacheStats.getValue().get("inserts");
+
+    CounterSnapshot.CounterDataPointSnapshot fqInsertsPre =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(core, 
SolrMetricTestUtils.FILTER_CACHE);
+    long fqInserts = (long) fqInsertsPre.getValue();
+
+    CounterSnapshot.CounterDataPointSnapshot qrInsertsPre =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            core, SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    long qrInserts = (long) qrInsertsPre.getValue();
 
     // This gets 0 docs back. Use 10000 instead of 1 for timeAllowed, and it 
gets 100 back and the
     // for loop below succeeds.
@@ -143,25 +133,29 @@ public class TimeAllowedTest extends SolrTestCaseJ4 {
         "Should have partial results",
         (Boolean) 
(header.get(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY)));
 
+    CounterSnapshot.CounterDataPointSnapshot qrInsertsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            core, SolrMetricTestUtils.QUERY_RESULT_CACHE);
     assertEquals(
         "Should NOT have inserted partial results in the cache!",
-        (long) queryCacheStats.getValue().get("inserts"),
+        (long) qrInsertsPost.getValue(),
         qrInserts);
 
-    assertEquals(
-        "Should NOT have another insert",
-        fqInserts,
-        (long) filterCacheStats.getValue().get("inserts"));
+    CounterSnapshot.CounterDataPointSnapshot fqInsertsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(core, 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("Should NOT have another insert", fqInserts, (long) 
fqInsertsPost.getValue());
 
     // At the end of all this, we should have no hits in the queryResultCache.
     response = JQ(req("q", "*:*", "fq", fq, "indent", "true", "timeAllowed", 
longTimeout));
 
     // Check that we did insert this one.
-    assertEquals("Hits should still be 0", (long) 
filterCacheStats.getValue().get("hits"), 0L);
-    assertEquals(
-        "Inserts should be bumped",
-        (long) filterCacheStats.getValue().get("inserts"),
-        fqInserts + 1);
+    CounterSnapshot.CounterDataPointSnapshot fqHitsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(core, 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("Hits should still be 0", (long) fqHitsPost.getValue(), 0L);
+
+    CounterSnapshot.CounterDataPointSnapshot fqInsertsPostSecond =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(core, 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("Inserts should be bumped", (long) 
fqInsertsPostSecond.getValue(), fqInserts + 1);
 
     res = (Map<?, ?>) fromJSONString(response);
     body = (Map<?, ?>) (res.get("response"));
@@ -179,22 +173,24 @@ public class TimeAllowedTest extends SolrTestCaseJ4 {
   public void testQueryResults() throws Exception {
     String q = "name:e*";
     SolrCore core = h.getCore();
-    MetricsMap queryCacheStats =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper<?>)
-                    core.getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.queryResultCache"))
-                .getGauge();
-    Map<String, Object> nl = queryCacheStats.getValue();
-    long inserts = (long) nl.get("inserts");
+
+    CounterSnapshot.CounterDataPointSnapshot insertsPre =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            core, SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    long inserts = (long) insertsPre.getValue();
+
+    CounterSnapshot.CounterDataPointSnapshot hitsPre =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(core, 
SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    long hits = (long) hitsPre.getValue();
 
     String response = JQ(req("q", q, "indent", "true", "timeAllowed", "1", 
"sleep", sleep));
 
     // The queryResultCache should NOT get an entry here.
-    nl = queryCacheStats.getValue();
-    assertEquals("Should NOT have inserted partial results!", inserts, (long) 
nl.get("inserts"));
+    CounterSnapshot.CounterDataPointSnapshot insertsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            core, SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    assertEquals(
+        "Should NOT have inserted partial results!", inserts, (long) 
insertsPost.getValue());
 
     Map<?, ?> res = (Map<?, ?>) fromJSONString(response);
     Map<?, ?> body = (Map<?, ?>) (res.get("response"));
@@ -208,9 +204,13 @@ public class TimeAllowedTest extends SolrTestCaseJ4 {
     response = JQ(req("q", q, "indent", "true", "timeAllowed", longTimeout));
 
     // Check that we did insert this one.
-    Map<String, Object> nl2 = queryCacheStats.getValue();
-    assertEquals("Hits should still be 0", (long) nl.get("hits"), (long) 
nl2.get("hits"));
-    assertTrue("Inserts should be bumped", inserts < (long) 
nl2.get("inserts"));
+    CounterSnapshot.CounterDataPointSnapshot hitsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(core, 
SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot insertsPost2 =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            core, SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    assertEquals("Hits should still be 0", hits, (long) hitsPost.getValue());
+    assertTrue("Inserts should be bumped", inserts < (long) 
insertsPost2.getValue());
 
     res = (Map<?, ?>) fromJSONString(response);
     body = (Map<?, ?>) (res.get("response"));
diff --git a/solr/core/src/test/org/apache/solr/search/TestCaffeineCache.java 
b/solr/core/src/test/org/apache/solr/search/TestCaffeineCache.java
index d70ea43a468..12d7813ec2d 100644
--- a/solr/core/src/test/org/apache/solr/search/TestCaffeineCache.java
+++ b/solr/core/src/test/org/apache/solr/search/TestCaffeineCache.java
@@ -16,10 +16,14 @@
  */
 package org.apache.solr.search;
 
+import static org.apache.solr.metrics.SolrMetricProducer.NAME_ATTR;
+
 import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.RemovalCause;
 import io.opentelemetry.api.common.Attributes;
+import io.prometheus.metrics.model.snapshots.CounterSnapshot;
+import io.prometheus.metrics.model.snapshots.Labels;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -35,6 +39,7 @@ import org.apache.lucene.util.Accountable;
 import org.apache.solr.SolrTestCase;
 import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.metrics.SolrMetricsContext;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.Test;
 
 /** Test for {@link CaffeineCache}. */
@@ -45,15 +50,18 @@ public class TestCaffeineCache extends SolrTestCase {
   String scope = TestUtil.randomSimpleString(random(), 2, 10);
 
   @Test
-  public void testSimple() {
+  public void testSimple() throws IOException {
     CaffeineCache<Integer, String> lfuCache = new CaffeineCache<>();
+    CaffeineCache<Integer, String> newLFUCache = new CaffeineCache<>();
+    String lfuCacheName = scope + "-1";
+    String newLfuCacheName = scope + "-2";
+
     SolrMetricsContext solrMetricsContext = new 
SolrMetricsContext(metricManager, registry, "foo");
-    // TODO SOLR-17458: Fix tests for OTEL
-    lfuCache.initializeMetrics(solrMetricsContext, Attributes.empty(), scope + 
"-1");
 
-    CaffeineCache<Integer, String> newLFUCache = new CaffeineCache<>();
-    // TODO SOLR-17458: Fix tests for OTEL
-    newLFUCache.initializeMetrics(solrMetricsContext, Attributes.empty(), 
scope + "-2");
+    lfuCache.initializeMetrics(
+        solrMetricsContext, Attributes.of(NAME_ATTR, lfuCacheName), 
"solr_cache");
+    newLFUCache.initializeMetrics(
+        solrMetricsContext, Attributes.of(NAME_ATTR, newLfuCacheName), 
"solr_cache");
 
     Map<String, String> params = new HashMap<>();
     params.put("size", "100");
@@ -69,31 +77,46 @@ public class TestCaffeineCache extends SolrTestCase {
     assertEquals("15", lfuCache.get(15));
     assertEquals("75", lfuCache.get(75));
     assertNull(lfuCache.get(110));
-    Map<String, Object> nl = lfuCache.getMetricsMap().getValue();
-    assertEquals(3L, nl.get("lookups"));
-    assertEquals(2L, nl.get("hits"));
-    assertEquals(101L, nl.get("inserts"));
 
-    assertNull(lfuCache.get(1)); // first item put in should be the first out
+    var prometheusReader = metricManager.getPrometheusMetricReader(registry);
+
+    var hitDatapoint = getCacheLookup(prometheusReader, lfuCacheName, 
"hit").getValue();
+    var missDatapoint = getCacheLookup(prometheusReader, lfuCacheName, 
"miss").getValue();
+    var insertDatapoint = getCacheOperation(prometheusReader, lfuCacheName, 
"inserts").getValue();
+    var evictionsDatapoint =
+        getCacheOperation(prometheusReader, lfuCacheName, 
"evictions").getValue();
+    assertEquals(3.0, hitDatapoint + missDatapoint, 0.001); // total lookups
+    assertEquals(2.0, hitDatapoint, 0.001);
+    assertEquals(101.0, insertDatapoint, 0.001);
+    assertNull(lfuCache.get(1));
 
     // Test autowarming
     newLFUCache.init(params, initObj, regenerator);
     newLFUCache.warm(null, lfuCache);
     newLFUCache.setState(SolrCache.State.LIVE);
-
     newLFUCache.put(103, "103");
     assertEquals("15", newLFUCache.get(15));
     assertEquals("75", newLFUCache.get(75));
     assertNull(newLFUCache.get(50));
-    nl = newLFUCache.getMetricsMap().getValue();
-    assertEquals(3L, nl.get("lookups"));
-    assertEquals(2L, nl.get("hits"));
-    assertEquals(1L, nl.get("inserts"));
-    assertEquals(0L, nl.get("evictions"));
-
-    assertEquals(7L, nl.get("cumulative_lookups"));
-    assertEquals(4L, nl.get("cumulative_hits"));
-    assertEquals(102L, nl.get("cumulative_inserts"));
+
+    var cumHitDatapoint = getCacheLookup(prometheusReader, newLfuCacheName, 
"hit").getValue();
+    var cumMissDatapoint = getCacheLookup(prometheusReader, newLfuCacheName, 
"miss").getValue();
+    var cumInsertDatapoint =
+        getCacheOperation(prometheusReader, newLfuCacheName, 
"inserts").getValue();
+    var cumEvictionsDatapoint =
+        getCacheOperation(prometheusReader, newLfuCacheName, 
"evictions").getValue();
+    var newHitDatapoint = cumHitDatapoint - hitDatapoint;
+    var newMissDatapoint = cumMissDatapoint - missDatapoint;
+    var newInsertDatapoint = cumInsertDatapoint - insertDatapoint;
+    var newEvictionDatapoint = cumEvictionsDatapoint - evictionsDatapoint;
+    assertEquals(3.0, newHitDatapoint + missDatapoint, 0.001); // total lookups
+    assertEquals(2.0, newMissDatapoint, 0.001);
+    assertEquals(1.0, newInsertDatapoint, 0.001);
+    assertEquals(0.0, newEvictionDatapoint, 0.001);
+
+    assertEquals(7.0, cumHitDatapoint + cumMissDatapoint, 0.001); // total 
cumulative lookups
+    assertEquals(4.0, cumHitDatapoint, 0.001);
+    assertEquals(102.0, cumInsertDatapoint, 0.001);
   }
 
   @Test
@@ -148,7 +171,7 @@ public class TestCaffeineCache extends SolrTestCase {
     int IDLE_TIME_SEC = 5;
     CountDownLatch removed = new CountDownLatch(1);
     AtomicReference<RemovalCause> removalCause = new AtomicReference<>();
-    CaffeineCache<String, String> cache =
+    try (CaffeineCache<String, String> cache =
         new CaffeineCache<>() {
           @Override
           public void onRemoval(String key, String value, RemovalCause cause) {
@@ -156,22 +179,23 @@ public class TestCaffeineCache extends SolrTestCase {
             removalCause.set(cause);
             removed.countDown();
           }
-        };
-    Map<String, String> params = new HashMap<>();
-    params.put("size", "6");
-    params.put("maxIdleTime", "" + IDLE_TIME_SEC);
-    cache.init(params, null, new NoOpRegenerator());
-
-    cache.put("foo", "bar");
-    assertEquals("bar", cache.get("foo"));
-    // sleep for at least the idle time before inserting other entries
-    // the eviction is piggy-backed on put()
-    Thread.sleep(TimeUnit.SECONDS.toMillis(IDLE_TIME_SEC * 2));
-    cache.put("abc", "xyz");
-    boolean await = removed.await(30, TimeUnit.SECONDS);
-    assertTrue("did not expire entry in in time", await);
-    assertEquals(RemovalCause.EXPIRED, removalCause.get());
-    assertNull(cache.get("foo"));
+        }) {
+      Map<String, String> params = new HashMap<>();
+      params.put("size", "6");
+      params.put("maxIdleTime", "" + IDLE_TIME_SEC);
+      cache.init(params, null, new NoOpRegenerator());
+
+      cache.put("foo", "bar");
+      assertEquals("bar", cache.get("foo"));
+      // sleep for at least the idle time before inserting other entries
+      // the eviction is piggy-backed on put()
+      Thread.sleep(TimeUnit.SECONDS.toMillis(IDLE_TIME_SEC * 2));
+      cache.put("abc", "xyz");
+      boolean await = removed.await(30, TimeUnit.SECONDS);
+      assertTrue("did not expire entry in in time", await);
+      assertEquals(RemovalCause.EXPIRED, removalCause.get());
+      assertNull(cache.get("foo"));
+    }
   }
 
   @Test
@@ -358,4 +382,33 @@ public class TestCaffeineCache extends SolrTestCase {
     cache.close();
     assertEquals(emptySize, cache.ramBytesUsed());
   }
+
+  private CounterSnapshot.CounterDataPointSnapshot getCacheOperation(
+      org.apache.solr.metrics.otel.FilterablePrometheusMetricReader 
prometheusReader,
+      String cacheName,
+      String operation) {
+    return SolrMetricTestUtils.getCounterDatapoint(
+        prometheusReader,
+        "solr_cache_ops",
+        Labels.builder()
+            .label("category", "CACHE")
+            .label("ops", operation)
+            .label("name", cacheName)
+            .label("otel_scope_name", "org.apache.solr")
+            .build());
+  }
+
+  private CounterSnapshot.CounterDataPointSnapshot getCacheLookup(
+      org.apache.solr.metrics.otel.FilterablePrometheusMetricReader 
prometheusReader,
+      String cacheName,
+      String result) {
+    var builder =
+        Labels.builder()
+            .label("category", "CACHE")
+            .label("name", cacheName)
+            .label("result", result)
+            .label("otel_scope_name", "org.apache.solr");
+    return SolrMetricTestUtils.getCounterDatapoint(
+        prometheusReader, "solr_cache_lookups", builder.build());
+  }
 }
diff --git 
a/solr/core/src/test/org/apache/solr/search/TestFiltersQueryCaching.java 
b/solr/core/src/test/org/apache/solr/search/TestFiltersQueryCaching.java
index 0319b1be6d0..42f1965dcf7 100644
--- a/solr/core/src/test/org/apache/solr/search/TestFiltersQueryCaching.java
+++ b/solr/core/src/test/org/apache/solr/search/TestFiltersQueryCaching.java
@@ -16,15 +16,14 @@
  */
 package org.apache.solr.search;
 
+import io.prometheus.metrics.model.snapshots.CounterSnapshot;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.core.SolrCore;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -49,28 +48,20 @@ public class TestFiltersQueryCaching extends SolrTestCaseJ4 
{
     assertU(commit());
   }
 
-  private static Map<String, Object> lookupFilterCacheMetrics(SolrCore core) {
-    return ((MetricsMap)
-            ((SolrMetricManager.GaugeWrapper<?>)
-                    core.getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.filterCache"))
-                .getGauge())
-        .getValue();
+  private static CounterSnapshot.CounterDataPointSnapshot 
getFilterCacheInserts(SolrCore core) {
+    return SolrMetricTestUtils.getCacheSearcherOpsInserts(core, 
SolrMetricTestUtils.FILTER_CACHE);
+  }
+
+  private static CounterSnapshot.CounterDataPointSnapshot 
getFilterCacheHits(SolrCore core) {
+    return SolrMetricTestUtils.getCacheSearcherOpsHits(core, 
SolrMetricTestUtils.FILTER_CACHE);
   }
 
   private static long lookupFilterCacheInserts(SolrCore core) {
-    return (long)
-        ((MetricsMap)
-                ((SolrMetricManager.GaugeWrapper<?>)
-                        core.getCoreMetricManager()
-                            .getRegistry()
-                            .getMetrics()
-                            .get("CACHE.searcher.filterCache"))
-                    .getGauge())
-            .getValue()
-            .get("inserts");
+    return (long) getFilterCacheInserts(core).getValue();
+  }
+
+  private static long lookupFilterCacheHits(SolrCore core) {
+    return (long) getFilterCacheHits(core).getValue();
   }
 
   @Test
@@ -120,7 +111,6 @@ public class TestFiltersQueryCaching extends SolrTestCaseJ4 
{
 
     h.reload();
     SolrCore core = h.getCore();
-    Map<String, Object> filterCacheMetrics;
     final String termQuery2 = "{!term f=field_s v='d1'}";
     final String filterTermQuery2 = "filter(" + termQuery2 + ")";
     assertJQ(
@@ -145,9 +135,8 @@ public class TestFiltersQueryCaching extends SolrTestCaseJ4 
{
             "true",
             "fq",
             random().nextBoolean() ? termQuery : filterTermQuery));
-    filterCacheMetrics = lookupFilterCacheMetrics(core);
-    assertEquals(2, (long) filterCacheMetrics.get("inserts")); // unchanged
-    assertEquals(1, (long) filterCacheMetrics.get("hits"));
+    assertEquals(2, lookupFilterCacheInserts(core)); // unchanged
+    assertEquals(1, lookupFilterCacheHits(core));
     JQ(
         req(
             "q",
@@ -156,9 +145,8 @@ public class TestFiltersQueryCaching extends SolrTestCaseJ4 
{
             "true",
             "fq",
             random().nextBoolean() ? termQuery2 : filterTermQuery2));
-    filterCacheMetrics = lookupFilterCacheMetrics(core);
-    assertEquals(2, (long) filterCacheMetrics.get("inserts")); // unchanged
-    assertEquals(2, (long) filterCacheMetrics.get("hits"));
+    assertEquals(2, lookupFilterCacheInserts(core)); // unchanged
+    assertEquals(2, lookupFilterCacheHits(core));
     JQ(
         req(
             "q",
@@ -175,9 +163,8 @@ public class TestFiltersQueryCaching extends SolrTestCaseJ4 
{
             "*",
             "sort",
             "id asc"));
-    filterCacheMetrics = lookupFilterCacheMetrics(core);
-    assertEquals(2, (long) filterCacheMetrics.get("inserts")); // unchanged
-    assertEquals(4, (long) filterCacheMetrics.get("hits"));
+    assertEquals(2, lookupFilterCacheInserts(core)); // unchanged
+    assertEquals(4, lookupFilterCacheHits(core));
     JQ(
         req(
             "q",
@@ -194,9 +181,8 @@ public class TestFiltersQueryCaching extends SolrTestCaseJ4 
{
             "*",
             "sort",
             "id asc"));
-    filterCacheMetrics = lookupFilterCacheMetrics(core);
-    assertEquals(3, (long) filterCacheMetrics.get("inserts")); // added 
top-level
-    assertEquals(6, (long) filterCacheMetrics.get("hits"));
+    assertEquals(3, lookupFilterCacheInserts(core)); // added top-level
+    assertEquals(6, lookupFilterCacheHits(core));
   }
 
   @Test
diff --git 
a/solr/core/src/test/org/apache/solr/search/TestMainQueryCaching.java 
b/solr/core/src/test/org/apache/solr/search/TestMainQueryCaching.java
index 8a298be2cb1..6ce6e1f5806 100644
--- a/solr/core/src/test/org/apache/solr/search/TestMainQueryCaching.java
+++ b/solr/core/src/test/org/apache/solr/search/TestMainQueryCaching.java
@@ -29,6 +29,7 @@ import org.apache.solr.common.util.SolrNamedThreadFactory;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.metrics.MetricsMap;
 import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -89,16 +90,7 @@ public class TestMainQueryCaching extends SolrTestCaseJ4 {
   }
 
   private static long coreToInserts(SolrCore core, String cacheName) {
-    return (long)
-        ((MetricsMap)
-                ((SolrMetricManager.GaugeWrapper<?>)
-                        core.getCoreMetricManager()
-                            .getRegistry()
-                            .getMetrics()
-                            .get("CACHE.searcher.".concat(cacheName)))
-                    .getGauge())
-            .getValue()
-            .get("inserts");
+    return (long) SolrMetricTestUtils.getCacheSearcherOpsInserts(core, 
cacheName).getValue();
   }
 
   private static long coreToSortCount(SolrCore core, String skipOrFull) {
@@ -112,6 +104,7 @@ public class TestMainQueryCaching extends SolrTestCaseJ4 {
             .getValue();
   }
 
+  // NOCOMMIT: Fix this once SolrIndexSearcher is migrated for OTEL
   private static long coreToMatchAllDocsInsertCount(SolrCore core) {
     return (long) coreToLiveDocsCacheMetrics(core).get("inserts");
   }
@@ -260,10 +253,11 @@ public class TestMainQueryCaching extends SolrTestCaseJ4 {
     Map<?, ?> body = (Map<?, ?>) (res.get("response"));
     SolrCore core = h.getCore();
     assertEquals("Bad matchAllDocs insert count", 1, 
coreToMatchAllDocsInsertCount(core));
-    assertEquals("Bad filterCache insert count", 0, coreToInserts(core, 
"filterCache"));
+    assertEquals(
+        "Bad filterCache insert count", 0, coreToInserts(core, 
SolrMetricTestUtils.FILTER_CACHE));
     assertEquals("Bad full sort count", 0, coreToSortCount(core, "full"));
     assertEquals("Should have exactly " + ALL_DOCS, ALL_DOCS, (long) 
(body.get("numFound")));
-    long queryCacheInsertCount = coreToInserts(core, "queryResultCache");
+    long queryCacheInsertCount = coreToInserts(core, 
SolrMetricTestUtils.QUERY_RESULT_CACHE);
     if (queryCacheInsertCount == expectCounters[0]) {
       // should be a hit, so all insert/sort-count metrics remain unchanged.
     } else {
@@ -415,7 +409,7 @@ public class TestMainQueryCaching extends SolrTestCaseJ4 {
     assertEquals(
         "Bad filterCache insert count",
         expectFilterCacheInsertCount,
-        coreToInserts(core, "filterCache"));
+        coreToInserts(core, SolrMetricTestUtils.FILTER_CACHE));
     assertEquals("Bad full sort count", expectFullSortCount, 
coreToSortCount(core, "full"));
     assertEquals("Bad skip sort count", expectSkipSortCount, 
coreToSortCount(core, "skip"));
     assertEquals(
diff --git 
a/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java 
b/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
index b3e05ae5cbb..e6856a19e93 100644
--- a/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
+++ b/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
@@ -26,8 +26,7 @@ import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -729,18 +728,11 @@ public class TestReRankQParserPlugin extends 
SolrTestCaseJ4 {
         "//result/doc[4]/str[@name='id'][.='3']",
         "//result/doc[5]/str[@name='id'][.='2']");
 
-    MetricsMap metrics =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper)
-                    h.getCore()
-                        .getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.queryResultCache"))
-                .getGauge();
-    Map<String, Object> stats = metrics.getValue();
-
-    long inserts = (Long) stats.get("inserts");
+    long inserts =
+        (long)
+            SolrMetricTestUtils.getCacheSearcherOpsInserts(
+                    h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE)
+                .getValue();
 
     assertTrue(inserts > 0);
 
@@ -770,9 +762,11 @@ public class TestReRankQParserPlugin extends 
SolrTestCaseJ4 {
         "//result/doc[4]/str[@name='id'][.='2']",
         "//result/doc[5]/str[@name='id'][.='1']");
 
-    stats = metrics.getValue();
-
-    long inserts1 = (Long) stats.get("inserts");
+    long inserts1 =
+        (long)
+            SolrMetricTestUtils.getCacheSearcherOpsInserts(
+                    h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE)
+                .getValue();
 
     // Last query was added to the cache
     assertTrue(inserts1 > inserts);
@@ -804,8 +798,11 @@ public class TestReRankQParserPlugin extends 
SolrTestCaseJ4 {
         "//result/doc[4]/str[@name='id'][.='2']",
         "//result/doc[5]/str[@name='id'][.='1']");
 
-    stats = metrics.getValue();
-    long inserts2 = (Long) stats.get("inserts");
+    long inserts2 =
+        (long)
+            SolrMetricTestUtils.getCacheSearcherOpsInserts(
+                    h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE)
+                .getValue();
     // Last query was NOT added to the cache
     assertEquals(inserts1, inserts2);
 
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java 
b/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
index 4456934937c..166d17e8e94 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
@@ -32,9 +32,8 @@ import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.FacetParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.apache.solr.util.SpatialUtils;
 import org.apache.solr.util.TestUtils;
 import org.junit.Before;
@@ -369,21 +368,15 @@ public class TestSolr4Spatial2 extends SolrTestCaseJ4 {
     if (testCache) {
       // The tricky thing is verifying the cache works correctly...
 
-      MetricsMap cacheMetrics =
-          (MetricsMap)
-              ((SolrMetricManager.GaugeWrapper)
-                      h.getCore()
-                          .getCoreMetricManager()
-                          .getRegistry()
-                          .getMetrics()
-                          .get("CACHE.searcher.perSegSpatialFieldCache_" + 
fieldName))
-                  .getGauge();
-      assertEquals("1", 
cacheMetrics.getValue().get("cumulative_inserts").toString());
-      assertEquals("0", 
cacheMetrics.getValue().get("cumulative_hits").toString());
+      long inserts = getSpatialFieldCacheInserts(fieldName);
+      long hits = getSpatialFieldCacheHits(fieldName);
+      assertEquals(1, inserts);
+      assertEquals(0, hits);
 
       // Repeat the query earlier
       assertJQ(sameReq, "/response/numFound==1", "/response/docs/[0]/id=='1'");
-      assertEquals("1", 
cacheMetrics.getValue().get("cumulative_hits").toString());
+      hits = getSpatialFieldCacheHits(fieldName);
+      assertEquals(1, hits);
 
       assertEquals("1 segment", 1, 
getSearcher().getRawReader().leaves().size());
       // Get key of first leaf reader -- this one contains the match for sure.
@@ -404,18 +397,8 @@ public class TestSolr4Spatial2 extends SolrTestCaseJ4 {
       Object leafKey2 = getFirstLeafReaderKey();
       // get the current instance of metrics - the old one may not represent 
the current cache
       // instance
-      cacheMetrics =
-          (MetricsMap)
-              ((SolrMetricManager.GaugeWrapper)
-                      h.getCore()
-                          .getCoreMetricManager()
-                          .getRegistry()
-                          .getMetrics()
-                          .get("CACHE.searcher.perSegSpatialFieldCache_" + 
fieldName))
-                  .getGauge();
-      assertEquals(
-          leafKey1.equals(leafKey2) ? "2" : "1",
-          cacheMetrics.getValue().get("cumulative_hits").toString());
+      hits = getSpatialFieldCacheHits(fieldName);
+      assertEquals(leafKey1.equals(leafKey2) ? 2 : 1, hits);
     }
 
     if (testHeatmap) {
@@ -456,6 +439,20 @@ public class TestSolr4Spatial2 extends SolrTestCaseJ4 {
     }
   }
 
+  private long getSpatialFieldCacheInserts(String fieldName) {
+    return (long)
+        SolrMetricTestUtils.getCacheSearcherOps(
+                h.getCore(), "perSegSpatialFieldCache_" + fieldName, "inserts")
+            .getValue();
+  }
+
+  private long getSpatialFieldCacheHits(String fieldName) {
+    return (long)
+        SolrMetricTestUtils.getCacheSearcherLookups(
+                h.getCore(), "perSegSpatialFieldCache_" + fieldName, "hit")
+            .getValue();
+  }
+
   protected SolrIndexSearcher getSearcher() {
     // neat trick; needn't deal with the hassle RefCounted
     return (SolrIndexSearcher) h.getCore().getInfoRegistry().get("searcher");
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 989140b28f0..8e9e4717676 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrCachePerf.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrCachePerf.java
@@ -16,7 +16,10 @@
  */
 package org.apache.solr.search;
 
+import static org.apache.solr.metrics.SolrMetricProducer.NAME_ATTR;
+
 import io.opentelemetry.api.common.Attributes;
+import io.prometheus.metrics.model.snapshots.Labels;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -30,6 +33,7 @@ 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.util.SolrMetricTestUtils;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runners.model.MultipleFailureException;
@@ -106,9 +110,10 @@ public class TestSolrCachePerf extends SolrTestCaseJ4 {
       CacheRegenerator cr = new NoOpRegenerator();
       Object o = cache.init(params, null, cr);
       cache.setState(SolrCache.State.LIVE);
-      // TODO SOLR-17458: Fix test later
       cache.initializeMetrics(
-          new SolrMetricsContext(metricManager, "foo", "bar"), 
Attributes.empty(), "foo");
+          new SolrMetricsContext(metricManager, "foo", "bar"),
+          Attributes.of(NAME_ATTR, "foo"),
+          "foo");
       AtomicBoolean stop = new AtomicBoolean();
       SummaryStatistics perImplRatio =
           ratioStats.computeIfAbsent(clazz.getSimpleName(), c -> new 
SummaryStatistics());
@@ -161,8 +166,20 @@ public class TestSolrCachePerf extends SolrTestCaseJ4 {
         throw new MultipleFailureException(new ArrayList<>(exceptions));
       }
       long stopTime = System.nanoTime();
-      Map<String, Object> metrics = 
cache.getSolrMetricsContext().getMetricsSnapshot();
-      
perImplRatio.addValue(Double.parseDouble(String.valueOf(metrics.get("CACHE.foo.hitratio"))));
+
+      var hitRatioDatapoint =
+          SolrMetricTestUtils.getGaugeDatapoint(
+              metricManager.getPrometheusMetricReader(
+                  cache.getSolrMetricsContext().getRegistryName()),
+              "solr_cache_hit_ratio",
+              Labels.builder()
+                  .label("category", "CACHE")
+                  .label("name", "foo")
+                  .label("otel_scope_name", "org.apache.solr")
+                  .build());
+
+      double hitRatio = hitRatioDatapoint != null ? 
hitRatioDatapoint.getValue() : 0.0;
+      perImplRatio.addValue(hitRatio);
       perImplTime.addValue((double) (stopTime - startTime));
       cache.close();
     }
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java 
b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
index 96d06362f72..243a5eab029 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
@@ -23,6 +23,7 @@ import static org.apache.solr.util.QueryMatchers.phraseQuery;
 import static org.apache.solr.util.QueryMatchers.termQuery;
 import static org.hamcrest.core.StringContains.containsString;
 
+import io.prometheus.metrics.model.snapshots.CounterSnapshot;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -49,14 +50,13 @@ import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.Utils;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.parser.QueryParser;
 import org.apache.solr.query.FilterQuery;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.NumberType;
 import org.apache.solr.schema.SchemaField;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -578,54 +578,40 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
     delI("777");
     assertU(commit()); // arg... commit no longer "commits" unless there has 
been a change.
 
-    final MetricsMap filterCacheStats =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper)
-                    h.getCore()
-                        .getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.filterCache"))
-                .getGauge();
-    assertNotNull(filterCacheStats);
-    final MetricsMap queryCacheStats =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper)
-                    h.getCore()
-                        .getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.queryResultCache"))
-                .getGauge();
-
-    assertNotNull(queryCacheStats);
-
-    long inserts = (Long) filterCacheStats.getValue().get("inserts");
-    long hits = (Long) filterCacheStats.getValue().get("hits");
+    CounterSnapshot.CounterDataPointSnapshot filterInsertsInitial =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.FILTER_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot filterHitsInitial =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(h.getCore(), 
SolrMetricTestUtils.FILTER_CACHE);
+
+    long inserts = (long) filterInsertsInitial.getValue();
+    long hits = (long) filterHitsInitial.getValue();
 
     assertJQ(
         req("q", "doesnotexist filter(id:1) filter(qqq_s:X) filter(abcdefg)"),
         "/response/numFound==2");
 
     inserts += 3;
-    assertEquals(
-        "wrong number of inserts",
-        inserts,
-        ((Long) filterCacheStats.getValue().get("inserts")).longValue());
-    assertEquals(
-        "wrong number of hits", hits, ((Long) 
filterCacheStats.getValue().get("hits")).longValue());
+    CounterSnapshot.CounterDataPointSnapshot filterInsertsAfter1 =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.FILTER_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot filterHitsAfter1 =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(h.getCore(), 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("wrong number of inserts", inserts, (long) 
filterInsertsAfter1.getValue());
+    assertEquals("wrong number of hits", hits, (long) 
filterHitsAfter1.getValue());
 
     assertJQ(
         req("q", "doesnotexist2 filter(id:1) filter(qqq_s:X) filter(abcdefg)"),
         "/response/numFound==2");
 
     hits += 3;
-    assertEquals(
-        "wrong number of inserts",
-        inserts,
-        ((Long) filterCacheStats.getValue().get("inserts")).longValue());
-    assertEquals(
-        "wrong number of hits", hits, ((Long) 
filterCacheStats.getValue().get("hits")).longValue());
+    CounterSnapshot.CounterDataPointSnapshot filterInsertsAfter2 =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.FILTER_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot filterHitsAfter2 =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(h.getCore(), 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("wrong number of inserts", inserts, (long) 
filterInsertsAfter2.getValue());
+    assertEquals("wrong number of hits", hits, (long) 
filterHitsAfter2.getValue());
 
     // make sure normal "fq" parameters also hit the cache the same way
     assertJQ(
@@ -633,12 +619,13 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
         "/response/numFound==0");
 
     hits += 3;
-    assertEquals(
-        "wrong number of inserts",
-        inserts,
-        ((Long) filterCacheStats.getValue().get("inserts")).longValue());
-    assertEquals(
-        "wrong number of hits", hits, ((Long) 
filterCacheStats.getValue().get("hits")).longValue());
+    CounterSnapshot.CounterDataPointSnapshot filterInsertsAfter3 =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.FILTER_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot filterHitsAfter3 =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(h.getCore(), 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("wrong number of inserts", inserts, (long) 
filterInsertsAfter3.getValue());
+    assertEquals("wrong number of hits", hits, (long) 
filterHitsAfter3.getValue());
 
     // try a query deeply nested in a FQ
     assertJQ(
@@ -651,12 +638,13 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
 
     inserts += 1; // +1 for top level fq
     hits += 3;
-    assertEquals(
-        "wrong number of inserts",
-        inserts,
-        ((Long) filterCacheStats.getValue().get("inserts")).longValue());
-    assertEquals(
-        "wrong number of hits", hits, ((Long) 
filterCacheStats.getValue().get("hits")).longValue());
+    CounterSnapshot.CounterDataPointSnapshot filterInsertsAfter4 =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.FILTER_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot filterHitsAfter4 =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(h.getCore(), 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("wrong number of inserts", inserts, (long) 
filterInsertsAfter4.getValue());
+    assertEquals("wrong number of hits", hits, (long) 
filterHitsAfter4.getValue());
 
     // retry the complex FQ and make sure hashCode/equals works as expected w/ 
filter queries
     assertJQ(
@@ -668,24 +656,26 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
         "/response/numFound==2");
 
     hits += 1; // top-level fq should have been found.
-    assertEquals(
-        "wrong number of inserts",
-        inserts,
-        ((Long) filterCacheStats.getValue().get("inserts")).longValue());
-    assertEquals(
-        "wrong number of hits", hits, ((Long) 
filterCacheStats.getValue().get("hits")).longValue());
+    CounterSnapshot.CounterDataPointSnapshot filterInsertsAfter5 =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.FILTER_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot filterHitsAfter5 =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(h.getCore(), 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("wrong number of inserts", inserts, (long) 
filterInsertsAfter5.getValue());
+    assertEquals("wrong number of hits", hits, (long) 
filterHitsAfter5.getValue());
 
     // try nested filter with multiple top-level args (i.e. a boolean query)
     assertJQ(req("q", "*:* +filter(id:1 filter(qqq_s:X) abcdefg)"), 
"/response/numFound==2");
 
     hits += 1; // the inner filter
     inserts += 1; // the outer filter
-    assertEquals(
-        "wrong number of inserts",
-        inserts,
-        ((Long) filterCacheStats.getValue().get("inserts")).longValue());
-    assertEquals(
-        "wrong number of hits", hits, ((Long) 
filterCacheStats.getValue().get("hits")).longValue());
+    CounterSnapshot.CounterDataPointSnapshot filterInsertsAfter6 =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.FILTER_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot filterHitsAfter6 =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(h.getCore(), 
SolrMetricTestUtils.FILTER_CACHE);
+    assertEquals("wrong number of inserts", inserts, (long) 
filterInsertsAfter6.getValue());
+    assertEquals("wrong number of hits", hits, (long) 
filterHitsAfter6.getValue());
 
     // test the score for a filter, and that default score is 0
     assertJQ(
diff --git a/solr/core/src/test/org/apache/solr/search/TestThinCache.java 
b/solr/core/src/test/org/apache/solr/search/TestThinCache.java
index de14da997ea..00c7d7a02a1 100644
--- a/solr/core/src/test/org/apache/solr/search/TestThinCache.java
+++ b/solr/core/src/test/org/apache/solr/search/TestThinCache.java
@@ -17,19 +17,19 @@
 package org.apache.solr.search;
 
 import io.opentelemetry.api.common.Attributes;
+import io.prometheus.metrics.model.snapshots.Labels;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import org.apache.lucene.tests.util.TestUtil;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.metrics.SolrMetricsContext;
 import org.apache.solr.util.EmbeddedSolrServerTestRule;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.apache.solr.util.TestHarness;
-import org.apache.solr.util.stats.MetricUtils;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
@@ -95,13 +95,11 @@ public class TestThinCache extends SolrTestCaseJ4 {
     ThinCache<Object, Integer, String> lfuCache = new ThinCache<>();
     lfuCache.setBacking(cacheScope, backing);
     SolrMetricsContext solrMetricsContext = new 
SolrMetricsContext(metricManager, registry, "foo");
-    // TODO SOLR-17458: Fix test later
     lfuCache.initializeMetrics(solrMetricsContext, Attributes.empty(), scope + 
"-1");
 
     Object cacheScope2 = new Object();
     ThinCache<Object, Integer, String> newLFUCache = new ThinCache<>();
     newLFUCache.setBacking(cacheScope2, backing);
-    // TODO SOLR-17458: Fix test later
     newLFUCache.initializeMetrics(solrMetricsContext, Attributes.empty(), 
scope + "-2");
 
     Map<String, String> params = new HashMap<>();
@@ -148,6 +146,8 @@ public class TestThinCache extends SolrTestCaseJ4 {
 
   @Test
   public void testInitCore() throws Exception {
+    String thinCacheName = "myNodeLevelCacheThin";
+    String nodeCacheName = "myNodeLevelCache";
     for (int i = 0; i < 20; i++) {
       assertU(adoc("id", Integer.toString(i)));
     }
@@ -155,28 +155,60 @@ public class TestThinCache extends SolrTestCaseJ4 {
     assertQ(req("q", "*:*", "fq", "id:0"));
     assertQ(req("q", "*:*", "fq", "id:0"));
     assertQ(req("q", "*:*", "fq", "id:1"));
-    Map<String, Object> nodeMetricsSnapshot =
-        MetricUtils.convertMetrics(
-            h.getCoreContainer().getMetricManager().registry("solr.node"),
-            List.of(
-                "CACHE.nodeLevelCache/myNodeLevelCacheThin",
-                "CACHE.nodeLevelCache/myNodeLevelCache"));
-    Map<String, Object> coreMetricsSnapshot =
-        MetricUtils.convertMetrics(
-            h.getCore().getCoreMetricManager().getRegistry(),
-            List.of("CACHE.searcher.filterCache"));
-
-    // check that metrics are accessible, and the core cache writes through to 
the node-level cache
-    Map<String, Number> assertions = Map.of("lookups", 3L, "hits", 1L, 
"inserts", 2L, "size", 2);
-    for (Map.Entry<String, Number> e : assertions.entrySet()) {
-      String key = e.getKey();
-      Number val = e.getValue();
-      assertEquals(
-          val, 
nodeMetricsSnapshot.get("CACHE.nodeLevelCache/myNodeLevelCacheThin.".concat(key)));
-      assertEquals(val, 
coreMetricsSnapshot.get("CACHE.searcher.filterCache.".concat(key)));
-    }
+
+    assertEquals(
+        3L,
+        getNodeCacheLookups(thinCacheName, "hit")
+            + getNodeCacheLookups(thinCacheName, "miss")); // total lookups
+    assertEquals(1L, getNodeCacheLookups(thinCacheName, "hit"));
+    assertEquals(2L, getNodeCacheOp(thinCacheName, "inserts"));
+
+    assertEquals(2, getNodeCacheSize(thinCacheName));
 
     // for the other node-level cache, simply check that metrics are accessible
-    assertEquals(0, 
nodeMetricsSnapshot.get("CACHE.nodeLevelCache/myNodeLevelCache.size"));
+    assertEquals(0, getNodeCacheSize(nodeCacheName));
+  }
+
+  private long getNodeCacheOp(String cacheName, String operation) {
+    var reader = 
h.getCoreContainer().getMetricManager().getPrometheusMetricReader("solr.node");
+    return (long)
+        SolrMetricTestUtils.getCounterDatapoint(
+                reader,
+                "solr_node_cache_ops",
+                Labels.builder()
+                    .label("category", "CACHE")
+                    .label("ops", operation)
+                    .label("name", cacheName)
+                    .label("otel_scope_name", "org.apache.solr")
+                    .build())
+            .getValue();
+  }
+
+  private long getNodeCacheLookups(String cacheName, String result) {
+    var reader = 
h.getCoreContainer().getMetricManager().getPrometheusMetricReader("solr.node");
+    var builder =
+        Labels.builder()
+            .label("category", "CACHE")
+            .label("name", cacheName)
+            .label("otel_scope_name", "org.apache.solr");
+    if (result != null) builder.label("result", result);
+
+    return (long)
+        SolrMetricTestUtils.getCounterDatapoint(reader, 
"solr_node_cache_lookups", builder.build())
+            .getValue();
+  }
+
+  private long getNodeCacheSize(String cacheName) {
+    var reader = 
h.getCoreContainer().getMetricManager().getPrometheusMetricReader("solr.node");
+    return (long)
+        SolrMetricTestUtils.getGaugeDatapoint(
+                reader,
+                "solr_node_cache_size",
+                Labels.builder()
+                    .label("category", "CACHE")
+                    .label("name", cacheName)
+                    .label("otel_scope_name", "org.apache.solr")
+                    .build())
+            .getValue();
   }
 }
diff --git a/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java 
b/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
index 66826e34ae8..bed4212bbca 100644
--- a/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
+++ b/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Objects;
 import javax.xml.xpath.XPathConstants;
 import org.apache.lucene.search.Query;
@@ -31,13 +30,12 @@ import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.join.ScoreMode;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrException;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.search.QParser;
 import org.apache.solr.search.SyntaxError;
 import org.apache.solr.util.BaseTestHarness;
 import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.After;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -49,6 +47,8 @@ public class BJQParserTest extends SolrTestCaseJ4 {
   private static final String[] klm = new String[] {"k", "l", "m"};
   private static final List<String> xyz = Arrays.asList("x", "y", "z");
   private static final String[] abcdef = new String[] {"a", "b", "c", "d", 
"e", "f"};
+  private static final String PER_SEG_FILTER_CACHE_NAME = "perSegFilter";
+  private static final String FILTER_CACHE_NAME = "filterCache";
 
   @ClassRule
   public static final TestRule noReverseMerge = 
RandomNoReverseMergePolicyFactory.createRule();
@@ -397,28 +397,15 @@ public class BJQParserTest extends SolrTestCaseJ4 {
   @Test
   public void testCacheHit() {
 
-    MetricsMap parentFilterCache =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper<?>)
-                    h.getCore()
-                        .getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.perSegFilter"))
-                .getGauge();
-    MetricsMap filterCache =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper<?>)
-                    h.getCore()
-                        .getCoreMetricManager()
-                        .getRegistry()
-                        .getMetrics()
-                        .get("CACHE.searcher.filterCache"))
-                .getGauge();
-
-    Map<String, Object> parentsBefore = parentFilterCache.getValue();
-
-    Map<String, Object> filtersBefore = filterCache.getValue();
+    // Get initial values
+    long parentLookupsBefore = getCacheLookups(PER_SEG_FILTER_CACHE_NAME);
+    ;
+    long parentHitsBefore = getCacheHits(PER_SEG_FILTER_CACHE_NAME);
+    long parentInsertsBefore = getCacheInserts(PER_SEG_FILTER_CACHE_NAME);
+    ;
+
+    long filterHitsBefore = getCacheHits(FILTER_CACHE_NAME);
+    long filterInsertsBefore = getCacheInserts(FILTER_CACHE_NAME);
 
     // it should be weird enough to be uniq
     String parentFilter = "parent_s:([a TO c] [d TO f])";
@@ -433,8 +420,7 @@ public class BJQParserTest extends SolrTestCaseJ4 {
         req("q", "*:*", "fq", "{!parent which=\"" + parentFilter + "\"}"),
         "//*[@numFound='6']");
 
-    assertEquals(
-        "didn't hit fqCache yet ", 0L, delta("hits", filterCache.getValue(), 
filtersBefore));
+    assertEquals("didn't hit fqCache yet ", 0L, 
getCacheHits(FILTER_CACHE_NAME) - filterHitsBefore);
 
     assertQ(
         "filter by join",
@@ -444,28 +430,24 @@ public class BJQParserTest extends SolrTestCaseJ4 {
     assertEquals(
         "in cache mode every request lookups",
         3,
-        delta("lookups", parentFilterCache.getValue(), parentsBefore));
+        getCacheLookups(PER_SEG_FILTER_CACHE_NAME) - parentLookupsBefore);
     assertEquals(
         "last two lookups causes hits",
         2,
-        delta("hits", parentFilterCache.getValue(), parentsBefore));
+        getCacheHits(PER_SEG_FILTER_CACHE_NAME) - parentHitsBefore);
     assertEquals(
         "the first lookup gets insert",
         1,
-        delta("inserts", parentFilterCache.getValue(), parentsBefore));
+        getCacheInserts(PER_SEG_FILTER_CACHE_NAME) - parentInsertsBefore);
 
     assertEquals(
         "true join query was not in fqCache",
         0L,
-        delta("hits", filterCache.getValue(), filtersBefore));
+        getCacheHits(FILTER_CACHE_NAME) - filterHitsBefore);
     assertEquals(
         "true join query is cached in fqCache",
         1L,
-        delta("inserts", filterCache.getValue(), filtersBefore));
-  }
-
-  private long delta(String key, Map<String, Object> a, Map<String, Object> b) 
{
-    return (Long) a.get(key) - (Long) b.get(key);
+        getCacheInserts(FILTER_CACHE_NAME) - filterInsertsBefore);
   }
 
   @Test
@@ -662,4 +644,16 @@ public class BJQParserTest extends SolrTestCaseJ4 {
     assertU("should be noop", delI("12275"));
     assertU("most of the time", commit());
   }
+
+  private long getCacheHits(String cacheName) {
+    return (long) SolrMetricTestUtils.getCacheSearcherOpsHits(h.getCore(), 
cacheName).getValue();
+  }
+
+  private long getCacheLookups(String cacheName) {
+    return (long) 
SolrMetricTestUtils.getCacheSearcherTotalLookups(h.getCore(), cacheName);
+  }
+
+  private long getCacheInserts(String cacheName) {
+    return (long) SolrMetricTestUtils.getCacheSearcherOpsInserts(h.getCore(), 
cacheName).getValue();
+  }
 }
diff --git 
a/solr/core/src/test/org/apache/solr/search/join/TestNestedDocsSort.java 
b/solr/core/src/test/org/apache/solr/search/join/TestNestedDocsSort.java
index 00c58558527..710bdf75975 100644
--- a/solr/core/src/test/org/apache/solr/search/join/TestNestedDocsSort.java
+++ b/solr/core/src/test/org/apache/solr/search/join/TestNestedDocsSort.java
@@ -16,7 +16,6 @@
  */
 package org.apache.solr.search.join;
 
-import java.util.Map;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.SolrTestCaseJ4;
@@ -26,6 +25,7 @@ import org.apache.solr.search.SolrCache;
 import org.apache.solr.search.SortSpec;
 import org.apache.solr.search.SortSpecParsing;
 import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
@@ -136,23 +136,21 @@ public class TestNestedDocsSort extends SolrTestCaseJ4 {
       @SuppressWarnings({"rawtypes"})
       final SolrCache cache = req.getSearcher().getCache("perSegFilter");
       assertNotNull(cache);
-      final Map<String, Object> state = 
cache.getSolrMetricsContext().getMetricsSnapshot();
-      String lookupsKey = null;
-      for (String key : state.keySet()) {
-        if (key.endsWith(".lookups")) {
-          lookupsKey = key;
-          break;
-        }
-      }
-      Number before = (Number) state.get(lookupsKey);
+      var core = req.getSearcher().getCore();
+      double before =
+          SolrMetricTestUtils.getCacheSearcherTotalLookups(
+              core, SolrMetricTestUtils.PER_SEG_FILTER_CACHE);
+
       parse("childfield(name_s1,$q) asc");
-      Number after = (Number) 
cache.getSolrMetricsContext().getMetricsSnapshot().get(lookupsKey);
+      double after =
+          SolrMetricTestUtils.getCacheSearcherTotalLookups(
+              core, SolrMetricTestUtils.PER_SEG_FILTER_CACHE);
       assertEquals(
           "parsing bjq lookups parent filter,"
               + "parsing sort spec lookups parent and child filters, "
               + "hopefully for the purpose",
           3,
-          after.intValue() - before.intValue());
+          (int) (after - before));
     } finally {
       req.close();
     }
diff --git 
a/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java 
b/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java
index fc47534bc13..5439e98e956 100644
--- a/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java
+++ b/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java
@@ -16,25 +16,23 @@
  */
 package org.apache.solr.search.join;
 
-import com.codahale.metrics.Metric;
+import io.prometheus.metrics.model.snapshots.CounterSnapshot;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Random;
 import org.apache.lucene.search.BoostQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.join.ScoreMode;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrException;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.search.QParser;
 import org.apache.solr.search.SolrCache;
+import org.apache.solr.util.SolrMetricTestUtils;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 
@@ -227,19 +225,17 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 {
   public void testCacheHit() throws Exception {
     indexDataForScoring();
 
-    Map<String, Metric> metrics =
-        h.getCoreContainer()
-            .getMetricManager()
-            .registry(h.getCore().getCoreMetricManager().getRegistryName())
-            .getMetrics();
-
-    @SuppressWarnings("rawtypes")
-    MetricsMap mm =
-        (MetricsMap)
-            ((SolrMetricManager.GaugeWrapper) 
metrics.get("CACHE.searcher.queryResultCache"))
-                .getGauge();
     {
-      Map<String, Object> statPre = mm.getValue();
+      double lookupsPre =
+          SolrMetricTestUtils.getCacheSearcherTotalLookups(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+      CounterSnapshot.CounterDataPointSnapshot hitsPre =
+          SolrMetricTestUtils.getCacheSearcherOpsHits(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+      CounterSnapshot.CounterDataPointSnapshot insertsPre =
+          SolrMetricTestUtils.getCacheSearcherOpsInserts(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+
       h.query(
           req(
               "q",
@@ -248,11 +244,21 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 {
               "id",
               "omitHeader",
               "true"));
-      assertHitOrInsert(mm.getValue(), statPre);
+
+      assertHitOrInsert(lookupsPre, hitsPre, insertsPre);
     }
 
     {
-      Map<String, Object> statPre = mm.getValue();
+      double lookupsPre =
+          SolrMetricTestUtils.getCacheSearcherTotalLookups(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+      CounterSnapshot.CounterDataPointSnapshot hitsPre =
+          SolrMetricTestUtils.getCacheSearcherOpsHits(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+      CounterSnapshot.CounterDataPointSnapshot insertsPre =
+          SolrMetricTestUtils.getCacheSearcherOpsInserts(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+
       h.query(
           req(
               "q",
@@ -261,11 +267,20 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 {
               "id",
               "omitHeader",
               "true"));
-      assertHit(mm.getValue(), statPre);
+
+      assertHit(lookupsPre, hitsPre, insertsPre);
     }
 
     {
-      Map<String, Object> statPre = mm.getValue();
+      double lookupsPre =
+          SolrMetricTestUtils.getCacheSearcherTotalLookups(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+      CounterSnapshot.CounterDataPointSnapshot hitsPre =
+          SolrMetricTestUtils.getCacheSearcherOpsHits(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+      CounterSnapshot.CounterDataPointSnapshot insertsPre =
+          SolrMetricTestUtils.getCacheSearcherOpsInserts(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
 
       Random r = random();
       boolean changed = false;
@@ -299,9 +314,19 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 {
                   "id",
                   "omitHeader",
                   "true"));
-      assertInsert(mm.getValue(), statPre);
 
-      statPre = mm.getValue();
+      assertInsert(lookupsPre, hitsPre, insertsPre);
+
+      double lookupsPreRepeat =
+          SolrMetricTestUtils.getCacheSearcherTotalLookups(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+      CounterSnapshot.CounterDataPointSnapshot hitsPreRepeat =
+          SolrMetricTestUtils.getCacheSearcherOpsHits(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+      CounterSnapshot.CounterDataPointSnapshot insertsPreRepeat =
+          SolrMetricTestUtils.getCacheSearcherOpsInserts(
+              h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+
       final String repeat =
           h.query(
               req(
@@ -320,7 +345,8 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 {
                   "id",
                   "omitHeader",
                   "true"));
-      assertHit(mm.getValue(), statPre);
+
+      assertHit(lookupsPreRepeat, hitsPreRepeat, insertsPreRepeat);
 
       assertEquals("lowercase shouldn't change anything", resp, repeat);
 
@@ -341,7 +367,8 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 {
     // however, it might be better to extract this method into a separate suite
     // for a while let's nuke a cache content, in case of repetitions
     @SuppressWarnings("rawtypes")
-    SolrCache cache = (SolrCache) 
h.getCore().getInfoRegistry().get("queryResultCache");
+    SolrCache cache =
+        (SolrCache) 
h.getCore().getInfoRegistry().get(SolrMetricTestUtils.QUERY_RESULT_CACHE);
     cache.clear();
   }
 
@@ -352,27 +379,71 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 {
     return l.get(r.nextInt(l.size()));
   }
 
-  private void assertInsert(Map<String, Object> current, final Map<String, 
Object> statPre) {
-    assertEquals("it lookups", 1, delta("lookups", current, statPre));
-    assertEquals("it doesn't hit", 0, delta("hits", current, statPre));
-    assertEquals("it inserts", 1, delta("inserts", current, statPre));
+  private void assertInsert(
+      double lookupsPre,
+      CounterSnapshot.CounterDataPointSnapshot hitsPre,
+      CounterSnapshot.CounterDataPointSnapshot insertsPre) {
+    double lookupsPost =
+        SolrMetricTestUtils.getCacheSearcherTotalLookups(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot hitsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot insertsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+
+    assertEquals("it lookups", 1, delta(lookupsPost, lookupsPre));
+    assertEquals("it doesn't hit", 0, delta(hitsPost, hitsPre));
+    assertEquals("it inserts", 1, delta(insertsPost, insertsPre));
   }
 
-  private void assertHit(Map<String, Object> current, final Map<String, 
Object> statPre) {
-    assertEquals("it lookups", 1, delta("lookups", current, statPre));
-    assertEquals("it hits", 1, delta("hits", current, statPre));
-    assertEquals("it doesn't insert", 0, delta("inserts", current, statPre));
+  private void assertHit(
+      double lookupsPre,
+      CounterSnapshot.CounterDataPointSnapshot hitsPre,
+      CounterSnapshot.CounterDataPointSnapshot insertsPre) {
+    double lookupsPost =
+        SolrMetricTestUtils.getCacheSearcherTotalLookups(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot hitsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot insertsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+
+    assertEquals("it lookups", 1, delta(lookupsPost, lookupsPre));
+    assertEquals("it hits", 1, delta(hitsPost, hitsPre));
+    assertEquals("it doesn't insert", 0, delta(insertsPost, insertsPre));
   }
 
-  private void assertHitOrInsert(Map<String, Object> current, final 
Map<String, Object> statPre) {
-    assertEquals("it lookups", 1, delta("lookups", current, statPre));
-    final long mayHit = delta("hits", current, statPre);
+  private void assertHitOrInsert(
+      double lookupsPre,
+      CounterSnapshot.CounterDataPointSnapshot hitsPre,
+      CounterSnapshot.CounterDataPointSnapshot insertsPre) {
+    double lookupsPost =
+        SolrMetricTestUtils.getCacheSearcherTotalLookups(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot hitsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsHits(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+    CounterSnapshot.CounterDataPointSnapshot insertsPost =
+        SolrMetricTestUtils.getCacheSearcherOpsInserts(
+            h.getCore(), SolrMetricTestUtils.QUERY_RESULT_CACHE);
+
+    assertEquals("it lookups", 1, delta(lookupsPost, lookupsPre));
+    final long mayHit = delta(hitsPost, hitsPre);
     assertTrue("it may hit", 0 == mayHit || 1 == mayHit);
-    assertEquals("or insert on cold", 1, delta("inserts", current, statPre) + 
mayHit);
+    assertEquals("or insert on cold", 1, delta(insertsPost, insertsPre) + 
mayHit);
+  }
+
+  private long delta(
+      CounterSnapshot.CounterDataPointSnapshot post, 
CounterSnapshot.CounterDataPointSnapshot pre) {
+    return delta(post.getValue(), pre.getValue());
   }
 
-  private long delta(String key, Map<String, Object> a, Map<String, Object> b) 
{
-    return (Long) a.get(key) - (Long) b.get(key);
+  private long delta(double post, double pre) {
+    return (long) post - (long) pre;
   }
 
   private void indexDataForScoring() {
diff --git 
a/solr/test-framework/src/java/org/apache/solr/util/SolrMetricTestUtils.java 
b/solr/test-framework/src/java/org/apache/solr/util/SolrMetricTestUtils.java
index 3531094cfc3..1fb3b0082cf 100644
--- a/solr/test-framework/src/java/org/apache/solr/util/SolrMetricTestUtils.java
+++ b/solr/test-framework/src/java/org/apache/solr/util/SolrMetricTestUtils.java
@@ -45,6 +45,12 @@ public final class SolrMetricTestUtils {
   private static final int MAX_ITERATIONS = 100;
   private static final SolrInfoBean.Category CATEGORIES[] = 
SolrInfoBean.Category.values();
 
+  // Cache name constants
+  public static final String QUERY_RESULT_CACHE = "queryResultCache";
+  public static final String FILTER_CACHE = "filterCache";
+  public static final String DOCUMENT_CACHE = "documentCache";
+  public static final String PER_SEG_FILTER_CACHE = "perSegFilter";
+
   public static String getRandomScope(Random random) {
     return getRandomScope(random, random.nextBoolean());
   }
@@ -246,6 +252,11 @@ public final class SolrMetricTestUtils {
     return getDataPoint(reader, metricName, labels, 
CounterSnapshot.CounterDataPointSnapshot.class);
   }
 
+  public static GaugeSnapshot.GaugeDataPointSnapshot getGaugeDatapoint(
+      PrometheusMetricReader reader, String metricName, Labels labels) {
+    return getDataPoint(reader, metricName, labels, 
GaugeSnapshot.GaugeDataPointSnapshot.class);
+  }
+
   public static HistogramSnapshot.HistogramDataPointSnapshot 
getHistogramDatapoint(
       PrometheusMetricReader reader, String metricName, Labels labels) {
     return getDataPoint(
@@ -304,6 +315,47 @@ public final class SolrMetricTestUtils {
             .build());
   }
 
+  public static CounterSnapshot.CounterDataPointSnapshot getCacheSearcherOps(
+      SolrCore core, String cacheName, String operation) {
+    return SolrMetricTestUtils.getCounterDatapoint(
+        core,
+        "solr_searcher_cache_ops",
+        SolrMetricTestUtils.newStandaloneLabelsBuilder(core)
+            .label("category", "CACHE")
+            .label("ops", operation)
+            .label("name", cacheName)
+            .build());
+  }
+
+  public static CounterSnapshot.CounterDataPointSnapshot 
getCacheSearcherLookups(
+      SolrCore core, String cacheName, String result) {
+    var builder =
+        SolrMetricTestUtils.newStandaloneLabelsBuilder(core)
+            .label("category", "CACHE")
+            .label("name", cacheName)
+            .label("result", result);
+    return SolrMetricTestUtils.getCounterDatapoint(
+        core, "solr_searcher_cache_lookups", builder.build());
+  }
+
+  public static CounterSnapshot.CounterDataPointSnapshot 
getCacheSearcherOpsHits(
+      SolrCore core, String cacheName) {
+    return SolrMetricTestUtils.getCacheSearcherLookups(core, cacheName, "hit");
+  }
+
+  public static double getCacheSearcherTotalLookups(SolrCore core, String 
cacheName) {
+    // Calculate lookup total as hits + misses
+    var hitDatapoint = SolrMetricTestUtils.getCacheSearcherOpsHits(core, 
cacheName);
+    var missDatapoint = SolrMetricTestUtils.getCacheSearcherLookups(core, 
cacheName, "miss");
+
+    return hitDatapoint.getValue() + missDatapoint.getValue();
+  }
+
+  public static CounterSnapshot.CounterDataPointSnapshot 
getCacheSearcherOpsInserts(
+      SolrCore core, String cacheName) {
+    return SolrMetricTestUtils.getCacheSearcherOps(core, cacheName, "inserts");
+  }
+
   public static class TestSolrMetricProducer implements SolrMetricProducer {
     SolrMetricsContext solrMetricsContext;
     private final Map<String, io.opentelemetry.api.metrics.LongCounter> 
counters = new HashMap<>();

Reply via email to