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