This is an automated email from the ASF dual-hosted git repository.
mkhludnev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new 4ceaa3284b8 SOLR-18455: actually disable metrics on <metrics
enabled="false"/> (#4902)
4ceaa3284b8 is described below
commit 4ceaa3284b8f5ec6c4a58bf851bda7fde42c1a0c
Author: Mikhail Khludnev <[email protected]>
AuthorDate: Mon Sep 21 09:58:20 2026 +0300
SOLR-18455: actually disable metrics on <metrics enabled="false"/> (#4902)
Co-authored-by: copilot-swe-agent[bot]
<[email protected]>
Co-authored-by: mkhludnev <[email protected]>
---
.../unreleased/SOLR-18455-metrics-disabled.yml | 12 ++++
.../java/org/apache/solr/core/CoreContainer.java | 2 +-
.../org/apache/solr/metrics/SolrMetricManager.java | 25 +++++--
.../cloud/CloudExitableDirectoryReaderTest.java | 2 +
.../org/apache/solr/cloud/TestPullReplica.java | 2 +
.../apache/solr/cloud/TestPullReplicaWithAuth.java | 2 +
.../SolrMetricsDisabledIntegrationTest.java | 84 ++++++++++++++++++++++
7 files changed, 124 insertions(+), 5 deletions(-)
diff --git a/changelog/unreleased/SOLR-18455-metrics-disabled.yml
b/changelog/unreleased/SOLR-18455-metrics-disabled.yml
new file mode 100644
index 00000000000..142738b4768
--- /dev/null
+++ b/changelog/unreleased/SOLR-18455-metrics-disabled.yml
@@ -0,0 +1,12 @@
+title: >
+ `<metrics enabled="false"/>` in `solr.xml` now actually disables the metrics
facility: no metric
+ exporter or JVM runtime metrics are set up, and instruments are created from
a no-op OpenTelemetry
+ meter, so registries no longer accumulate metrics (and the memory they
retain) for a disabled node.
+type: fixed
+authors:
+ - name: Mikhail Khludnev
+ nick: mkhludnev
+ url: https://home.apache.org/phonebook.html?uid=mkhl
+links:
+ - name: SOLR-18455
+ url: https://issues.apache.org/jira/browse/SOLR-18455
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 64916561070..ef6852a14db 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -407,7 +407,7 @@ public class CoreContainer {
this.solrCores = SolrCores.newSolrCores(this);
this.nodeKeyPair = new SolrNodeKeyPair(cfg.getCloudConfig());
OpenTelemetryConfigurator.initializeOpenTelemetrySdk(cfg, loader);
- this.metricManager = new SolrMetricManager(loader);
+ this.metricManager = new SolrMetricManager(loader,
cfg.getMetricsConfig().isEnabled());
this.tracer = TraceUtils.getGlobalTracer();
containerHandlers.put(PublicKeyHandler.PATH, new
PublicKeyHandler(nodeKeyPair));
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 336610c536d..f68ee18b2e6 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
@@ -36,6 +36,7 @@ import io.opentelemetry.api.metrics.LongHistogram;
import io.opentelemetry.api.metrics.LongHistogramBuilder;
import io.opentelemetry.api.metrics.LongUpDownCounter;
import io.opentelemetry.api.metrics.LongUpDownCounterBuilder;
+import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.api.metrics.ObservableDoubleCounter;
import io.opentelemetry.api.metrics.ObservableDoubleGauge;
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
@@ -123,6 +124,7 @@ public class SolrMetricManager {
new ConcurrentHashMap<>();
private final MetricExporter metricExporter;
+ private final boolean enabled;
private OtelRuntimeJvmMetrics otelRuntimeJvmMetrics;
private static final List<Double> SOLR_NANOSECOND_HISTOGRAM_BOUNDARIES =
@@ -143,12 +145,24 @@ public class SolrMetricManager {
1_000_000_000.0);
public SolrMetricManager(MetricExporter exporter) {
+ this(exporter, true);
+ }
+
+ public SolrMetricManager(MetricExporter exporter, boolean enabled) {
metricExporter = exporter;
+ this.enabled = enabled;
}
public SolrMetricManager(SolrResourceLoader loader) {
- this.metricExporter = loadMetricExporter(loader);
- this.otelRuntimeJvmMetrics = new OtelRuntimeJvmMetrics().initialize(this,
JVM_REGISTRY);
+ this(loader, true);
+ }
+
+ public SolrMetricManager(SolrResourceLoader loader, boolean enabled) {
+ this.enabled = enabled;
+ this.metricExporter = enabled ? loadMetricExporter(loader) : null;
+ if (enabled) {
+ this.otelRuntimeJvmMetrics = new
OtelRuntimeJvmMetrics().initialize(this, JVM_REGISTRY);
+ }
}
public LongCounter longCounter(
@@ -429,9 +443,12 @@ public class SolrMetricManager {
* Get (or create if not present) a named {@link SdkMeterProvider}.
*
* @param providerName name of the meter provider and prometheus metric
reader
- * @return existing or newly created meter provider
+ * @return existing or newly created meter provider, or a no-op one when
metrics are disabled
*/
- public SdkMeterProvider meterProvider(String providerName) {
+ public MeterProvider meterProvider(String providerName) {
+ if (!enabled) {
+ return MeterProvider.noop();
+ }
providerName = enforcePrefix(providerName);
return meterProviderAndReaders
.computeIfAbsent(
diff --git
a/solr/core/src/test/org/apache/solr/cloud/CloudExitableDirectoryReaderTest.java
b/solr/core/src/test/org/apache/solr/cloud/CloudExitableDirectoryReaderTest.java
index 28bd7dc9d4b..4cad3210323 100644
---
a/solr/core/src/test/org/apache/solr/cloud/CloudExitableDirectoryReaderTest.java
+++
b/solr/core/src/test/org/apache/solr/cloud/CloudExitableDirectoryReaderTest.java
@@ -72,6 +72,8 @@ public class CloudExitableDirectoryReaderTest extends
SolrCloudTestCase {
@BeforeClass
public static void setupCluster() throws Exception {
+ // this test inspects node level request metrics
+ System.setProperty("metricsEnabled", "true");
// create one more node than shard, so that we also test the case of
proxied requests.
MiniSolrCloudCluster.Builder clusterBuilder =
configureCluster(3)
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
index d3e4c120b13..55254077e46 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
@@ -90,6 +90,8 @@ public class TestPullReplica extends SolrCloudTestCase {
@BeforeClass
public static void createTestCluster() throws Exception {
+ // this test inspects core level update metrics
+ System.setProperty("metricsEnabled", "true");
System.setProperty("solr.solrj.cloud.max.stale.retries", "1");
System.setProperty("zkReaderGetLeaderRetryTimeoutMs", "1000");
diff --git
a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaWithAuth.java
b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaWithAuth.java
index 8d3fea023d3..f79599103ce 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaWithAuth.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaWithAuth.java
@@ -53,6 +53,8 @@ public class TestPullReplicaWithAuth extends
SolrCloudTestCase {
@BeforeClass
public static void setupClusterWithSecurityEnabled() throws Exception {
+ // this test inspects core level update metrics
+ System.setProperty("metricsEnabled", "true");
configureCluster(2)
.addConfig("conf", configset("cloud-minimal"))
.withSecurityJson(SecurityJson.SIMPLE)
diff --git
a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsDisabledIntegrationTest.java
b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsDisabledIntegrationTest.java
new file mode 100644
index 00000000000..13e8d943503
--- /dev/null
+++
b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsDisabledIntegrationTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.metrics;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.NodeConfig;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrXmlConfig;
+import org.apache.solr.util.TestHarness;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SolrMetricsDisabledIntegrationTest extends SolrTestCaseJ4 {
+ private CoreContainer cc;
+ private SolrMetricManager metricManager;
+
+ @Before
+ public void beforeTest() throws Exception {
+ Path home = TEST_PATH();
+ // SolrTestCaseJ4 installs SystemPropertiesRestoreRule as a method @Rule,
so this is
+ // reverted after each test method; no manual save/restore needed.
+ System.setProperty("metricsEnabled", "false");
+
+ String solrXml = Files.readString(home.resolve("solr.xml"),
StandardCharsets.UTF_8);
+ NodeConfig cfg = SolrXmlConfig.fromString(home, solrXml);
+ cc =
+ createCoreContainer(
+ cfg,
+ new TestHarness.TestCoresLocator(
+ DEFAULT_TEST_CORENAME,
+ initAndGetDataDir().toString(),
+ "solrconfig.xml",
+ "schema.xml"));
+ h.coreName = DEFAULT_TEST_CORENAME;
+ metricManager = cc.getMetricManager();
+ }
+
+ @After
+ public void afterTest() {
+ if (metricManager != null) {
+ deleteCore();
+ }
+ }
+
+ @Test
+ public void testMetricsDisabledPreventsNodeAndCoreRegistries() throws
Exception {
+ assertFalse(cc.getConfig().getMetricsConfig().isEnabled());
+ assertTrue(metricManager.registryNames().isEmpty());
+ assertNull(metricManager.getPrometheusMetricReader("solr.node"));
+
+ try (SolrCore core = cc.getCore(DEFAULT_TEST_CORENAME)) {
+ assertNotNull(core);
+ assertNull(
+
metricManager.getPrometheusMetricReader(core.getCoreMetricManager().getRegistryName()));
+ }
+
+ assertQ(req("q", "*:*"), "//result[@numFound='0']");
+ assertU(adoc("id", "1"));
+ assertU(commit());
+
+ assertTrue(metricManager.registryNames().isEmpty());
+ assertNull(metricManager.getPrometheusMetricReader("solr.node"));
+ }
+}