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<>();