diff --git a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java index d34b482402a..243f3a83cdb 100644 --- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java +++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java @@ -42,13 +42,13 @@ import org.apache.solr.core.PluginInfo; import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrInfoBean; -import org.apache.solr.metrics.SolrDelegateRegistryMetricsContext; import org.apache.solr.metrics.SolrMetricManager; -import org.apache.solr.metrics.SolrMetricProducer; import org.apache.solr.metrics.SolrMetricsContext; import org.apache.solr.metrics.otel.OtelUnit; import org.apache.solr.metrics.otel.instruments.AttributedLongCounter; import org.apache.solr.metrics.otel.instruments.AttributedLongTimer; +import org.apache.solr.metrics.otel.instruments.DualRegistryAttributedLongCounter; +import org.apache.solr.metrics.otel.instruments.DualRegistryAttributedLongTimer; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.response.SolrQueryResponse; @@ -168,21 +168,13 @@ public SolrMetricsContext getSolrMetricsContext() { @Override public void initializeMetrics( SolrMetricsContext parentContext, Attributes attributes, String scope) { - if (aggregateNodeLevelMetricsEnabled) { - this.solrMetricsContext = - new SolrDelegateRegistryMetricsContext( - parentContext.getMetricManager(), - parentContext.getRegistryName(), - SolrMetricProducer.getUniqueMetricTag(this, parentContext.getTag()), - SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)); - } else { - this.solrMetricsContext = parentContext.getChildContext(this); - } + this.solrMetricsContext = parentContext.getChildContext(this); metrics = new HandlerMetrics( solrMetricsContext, - attributes.toBuilder().put(CATEGORY_ATTR, getCategory().toString()).build()); + attributes.toBuilder().put(CATEGORY_ATTR, getCategory().toString()).build(), + aggregateNodeLevelMetricsEnabled); // NOCOMMIT: I don't see value in this metric solrMetricsContext.gauge( @@ -198,7 +190,8 @@ public static class HandlerMetrics { null, new MetricsConfig.MetricsConfigBuilder().setEnabled(false).build()), "NO_OP", "NO_OP"), - Attributes.empty()); + Attributes.empty(), + false); public AttributedLongCounter requests; public AttributedLongCounter numServerErrors; @@ -206,54 +199,124 @@ public static class HandlerMetrics { public AttributedLongCounter numTimeouts; public AttributedLongTimer requestTimes; - public HandlerMetrics(SolrMetricsContext solrMetricsContext, Attributes attributes) { - - LongCounter requestMetric; - LongCounter errorRequestMetric; - LongCounter timeoutRequestMetric; - LongHistogram requestTimeMetric; - - if (solrMetricsContext.getRegistryName().equals("solr.node")) { - requestMetric = - solrMetricsContext.longCounter("solr_node_requests", "Http Solr node requests"); - errorRequestMetric = - solrMetricsContext.longCounter( - "solr_node_requests_errors", "HTTP Solr node request errors"); - timeoutRequestMetric = - solrMetricsContext.longCounter( - "solr_node_requests_timeout", "HTTP Solr node request timeouts"); - requestTimeMetric = - solrMetricsContext.longHistogram( - "solr_node_requests_times", "HTTP Solr node request times", OtelUnit.MILLISECONDS); + public HandlerMetrics( + SolrMetricsContext solrMetricsContext, + Attributes coreAttributes, + boolean aggregateNodeLevelMetricsEnabled) { + + if (aggregateNodeLevelMetricsEnabled) { + createDualRegistryMetrics(solrMetricsContext, coreAttributes); } else { - requestMetric = - solrMetricsContext.longCounter("solr_core_requests", "HTTP Solr core requests"); - errorRequestMetric = - solrMetricsContext.longCounter( - "solr_core_requests_errors", "HTTP Solr core request errors"); - timeoutRequestMetric = - solrMetricsContext.longCounter( - "solr_core_requests_timeout", "HTTP Solr core request timeouts"); - requestTimeMetric = - solrMetricsContext.longHistogram( - "solr_core_requests_times", "HTTP Solr core request times", OtelUnit.MILLISECONDS); + createSingleRegistryMetrics(solrMetricsContext, coreAttributes); } + } - requests = new AttributedLongCounter(requestMetric, attributes); + private void createDualRegistryMetrics( + SolrMetricsContext solrCoreMetricsContext, Attributes coreAttributes) { + SolrMetricsContext solrNodeMetricsContext = + new SolrMetricsContext( + solrCoreMetricsContext.getMetricManager(), + SolrMetricManager.getRegistryName(SolrInfoBean.Group.node), + null); + + Attributes nodeAttributes = + Attributes.builder() + .put(CATEGORY_ATTR, coreAttributes.get(CATEGORY_ATTR)) + .put(HANDLER_ATTR, coreAttributes.get(HANDLER_ATTR)) + .build(); + + requests = + new DualRegistryAttributedLongCounter( + requestCounter(solrCoreMetricsContext, false), coreAttributes, + requestCounter(solrNodeMetricsContext, true), nodeAttributes); + numServerErrors = + new DualRegistryAttributedLongCounter( + requestErrorCounter(solrCoreMetricsContext, false), + coreAttributes.toBuilder().put(AttributeKey.stringKey("source"), "server").build(), + requestErrorCounter(solrNodeMetricsContext, true), + nodeAttributes.toBuilder().put(AttributeKey.stringKey("source"), "server").build()); + + numClientErrors = + new DualRegistryAttributedLongCounter( + requestErrorCounter(solrCoreMetricsContext, false), + coreAttributes.toBuilder().put(AttributeKey.stringKey("source"), "client").build(), + requestErrorCounter(solrNodeMetricsContext, true), + nodeAttributes.toBuilder().put(AttributeKey.stringKey("source"), "client").build()); + numTimeouts = + new DualRegistryAttributedLongCounter( + requestTimeoutCounter(solrCoreMetricsContext, false), coreAttributes, + requestTimeoutCounter(solrNodeMetricsContext, true), nodeAttributes); + requestTimes = + new DualRegistryAttributedLongTimer( + requestTimeHistogram(solrCoreMetricsContext, false), coreAttributes, + requestTimeHistogram(solrNodeMetricsContext, true), nodeAttributes); + } + private void createSingleRegistryMetrics( + SolrMetricsContext solrMetricsContext, Attributes coreAttributes) { + boolean isNodeRegistry = + solrMetricsContext + .getRegistryName() + .equals(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)); + + Attributes attributes = + isNodeRegistry + ? Attributes.builder() + .put(CATEGORY_ATTR, coreAttributes.get(CATEGORY_ATTR)) + .put(HANDLER_ATTR, coreAttributes.get(HANDLER_ATTR)) + .build() + : coreAttributes; + + requests = + new AttributedLongCounter(requestCounter(solrMetricsContext, isNodeRegistry), attributes); numServerErrors = new AttributedLongCounter( - errorRequestMetric, + requestErrorCounter(solrMetricsContext, isNodeRegistry), attributes.toBuilder().put(AttributeKey.stringKey("source"), "server").build()); - numClientErrors = new AttributedLongCounter( - errorRequestMetric, + requestErrorCounter(solrMetricsContext, isNodeRegistry), attributes.toBuilder().put(AttributeKey.stringKey("source"), "client").build()); + numTimeouts = + new AttributedLongCounter( + requestTimeoutCounter(solrMetricsContext, isNodeRegistry), attributes); + requestTimes = + new AttributedLongTimer( + requestTimeHistogram(solrMetricsContext, isNodeRegistry), attributes); + } + + private LongCounter requestCounter( + SolrMetricsContext solrMetricsContext, boolean isNodeRegistry) { + return (isNodeRegistry) + ? solrMetricsContext.longCounter("solr_node_requests", "HTTP Solr node requests") + : solrMetricsContext.longCounter("solr_core_requests", "HTTP Solr core requests"); + } + + private LongCounter requestErrorCounter( + SolrMetricsContext solrMetricsContext, boolean isNodeRegistry) { + return (isNodeRegistry) + ? solrMetricsContext.longCounter( + "solr_node_requests_errors", "HTTP Solr node request errors") + : solrMetricsContext.longCounter( + "solr_core_requests_errors", "HTTP Solr core request errors"); + } - numTimeouts = new AttributedLongCounter(timeoutRequestMetric, attributes); + private LongCounter requestTimeoutCounter( + SolrMetricsContext solrMetricsContext, boolean isNodeRegistry) { + return (isNodeRegistry) + ? solrMetricsContext.longCounter( + "solr_node_requests_timeout", "HTTP Solr node request timeouts") + : solrMetricsContext.longCounter( + "solr_core_requests_timeout", "HTTP Solr core request timeouts"); + } - requestTimes = new AttributedLongTimer(requestTimeMetric, attributes); + private LongHistogram requestTimeHistogram( + SolrMetricsContext solrMetricsContext, boolean isNodeRegistry) { + return (isNodeRegistry) + ? solrMetricsContext.longHistogram( + "solr_node_requests_times", "HTTP Solr node request times", OtelUnit.MILLISECONDS) + : solrMetricsContext.longHistogram( + "solr_core_requests_times", "HTTP Solr core request times", OtelUnit.MILLISECONDS); } } diff --git a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java index 67ae1c29c63..84e1db376a3 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java @@ -98,8 +98,6 @@ public class SearchHandler extends RequestHandlerBase static final String INIT_FIRST_COMPONENTS = "first-components"; static final String INIT_LAST_COMPONENTS = "last-components"; - protected static final String SHARD_HANDLER_SUFFIX = "[shard]"; - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); /** @@ -171,7 +169,8 @@ public void initializeMetrics( .putAll(attributes) .put(CATEGORY_ATTR, getCategory().toString()) .put(INTERNAL_ATTR, true) - .build()); + .build(), + false); } @Override diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedDoubleCounter.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedDoubleCounter.java index 43adf8ad087..bf345bb69df 100644 --- a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedDoubleCounter.java +++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedDoubleCounter.java @@ -30,7 +30,7 @@ public AttributedDoubleCounter(DoubleCounter counter, Attributes attributes) { } public void inc() { - add(1.0); + counter.add(1.0, attributes); } public void add(Double value) { diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedDoubleUpDownCounter.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedDoubleUpDownCounter.java index 23c0d3b9a53..02456e6c8fd 100644 --- a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedDoubleUpDownCounter.java +++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedDoubleUpDownCounter.java @@ -30,11 +30,11 @@ public AttributedDoubleUpDownCounter(DoubleUpDownCounter upDownCounter, Attribut } public void inc() { - add(1.0); + upDownCounter.add(1.0, attributes); } public void dec() { - add(-1.0); + upDownCounter.add(-1.0, attributes); } public void add(Double value) { diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedLongCounter.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedLongCounter.java index f33b4784c53..82d0ba39d46 100644 --- a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedLongCounter.java +++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedLongCounter.java @@ -30,7 +30,7 @@ public AttributedLongCounter(LongCounter baseCounter, Attributes attributes) { } public void inc() { - add(1L); + baseCounter.add(1L, attributes); } public void add(Long value) { diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedLongUpDownCounter.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedLongUpDownCounter.java index 91487c9e677..daf69abfb9d 100644 --- a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedLongUpDownCounter.java +++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedLongUpDownCounter.java @@ -30,11 +30,11 @@ public AttributedLongUpDownCounter(LongUpDownCounter upDownCounter, Attributes a } public void inc() { - add(1L); + upDownCounter.add(1L, attributes); } public void dec() { - add(-1L); + upDownCounter.add(-1L, attributes); } public void add(Long value) { diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongCounter.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongCounter.java new file mode 100644 index 00000000000..b7cc1379479 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongCounter.java @@ -0,0 +1,50 @@ +/* + * 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.instruments; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.LongCounter; + +/** + * An AttributedLongCounter that writes to both core and node registries with corresponding + * attributes. + */ +public class DualRegistryAttributedLongCounter extends AttributedLongCounter { + + private final AttributedLongCounter nodeCounter; + + public DualRegistryAttributedLongCounter( + LongCounter coreCounter, + Attributes coreAttributes, + LongCounter nodeCounter, + Attributes nodeAttributes) { + super(coreCounter, coreAttributes); + this.nodeCounter = new AttributedLongCounter(nodeCounter, nodeAttributes); + } + + @Override + public void inc() { + super.inc(); + nodeCounter.inc(); + } + + @Override + public void add(Long value) { + super.add(value); + nodeCounter.add(value); + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongTimer.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongTimer.java new file mode 100644 index 00000000000..73f45e3d533 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongTimer.java @@ -0,0 +1,44 @@ +/* + * 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.instruments; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.LongHistogram; + +/** + * An AttributedLongTimer that records to both core and node registries with corresponding + * attributes. + */ +public class DualRegistryAttributedLongTimer extends AttributedLongTimer { + + private final AttributedLongTimer nodeTimer; + + public DualRegistryAttributedLongTimer( + LongHistogram coreHistogram, + Attributes coreAttributes, + LongHistogram nodeHistogram, + Attributes nodeAttributes) { + super(coreHistogram, coreAttributes); + this.nodeTimer = new AttributedLongTimer(nodeHistogram, nodeAttributes); + } + + @Override + public void record(Long value) { + super.record(value); + nodeTimer.record(value); + } +} diff --git a/solr/core/src/test/org/apache/solr/handler/RequestHandlerBaseTest.java b/solr/core/src/test/org/apache/solr/handler/RequestHandlerBaseTest.java index 74d3d6b2510..951c7f69385 100644 --- a/solr/core/src/test/org/apache/solr/handler/RequestHandlerBaseTest.java +++ b/solr/core/src/test/org/apache/solr/handler/RequestHandlerBaseTest.java @@ -196,6 +196,8 @@ private RequestHandlerBase.HandlerMetrics createHandlerMetrics() { when(metricsContext.longHistogram(any(), any())).thenReturn(mockLongHistogram); return new RequestHandlerBase.HandlerMetrics( - metricsContext, Attributes.of(AttributeKey.stringKey("/handler"), "/someBaseMetricPath")); + metricsContext, + Attributes.of(AttributeKey.stringKey("/handler"), "/someBaseMetricPath"), + false); } } diff --git a/solr/core/src/test/org/apache/solr/handler/RequestHandlerMetricsTest.java b/solr/core/src/test/org/apache/solr/handler/RequestHandlerMetricsTest.java index 467094ccd62..6a85abd322e 100644 --- a/solr/core/src/test/org/apache/solr/handler/RequestHandlerMetricsTest.java +++ b/solr/core/src/test/org/apache/solr/handler/RequestHandlerMetricsTest.java @@ -16,19 +16,17 @@ */ package org.apache.solr.handler; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; import java.io.IOException; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; import org.apache.solr.client.solrj.SolrQuery; -import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; -import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.util.NamedList; +import org.apache.solr.core.SolrCore; +import org.apache.solr.metrics.SolrMetricTestUtils; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -54,11 +52,7 @@ public static void afterClass() { System.clearProperty("metricsEnabled"); } - // NOCOMMIT: Need to fix aggregateNodeLevelMetricsEnabled for OTEL. Delegate registries currently - // do not play nice with OTEL instrumentation @Test - @AwaitsFix(bugUrl = "https://issues.apache.org/jira/browse/SOLR-17458") - @SuppressWarnings({"unchecked"}) public void testAggregateNodeLevelMetrics() throws SolrServerException, IOException { String collection1 = "testRequestHandlerMetrics1"; String collection2 = "testRequestHandlerMetrics2"; @@ -83,97 +77,54 @@ public void testAggregateNodeLevelMetrics() throws SolrServerException, IOExcept cloudClient.query(collection1, solrQuery); cloudClient.query(collection2, solrQuery); - NamedList response = - cloudClient.request( - new GenericSolrRequest( - SolrRequest.METHOD.GET, "/admin/metrics", SolrRequest.SolrRequestType.ADMIN)); - - NamedList metrics = (NamedList) response.get("metrics"); - - final double[] minQueryTime = {Double.MAX_VALUE}; - final double[] maxQueryTime = {-1.0}; - final double[] minUpdateTime = {Double.MAX_VALUE}; - final double[] maxUpdateTime = {-1.0}; - Set> coreMetrics = new HashSet<>(); - metrics.forEach( - (key, coreMetric) -> { - if (key.startsWith("solr.core.testRequestHandlerMetrics")) { - coreMetrics.add((NamedList) coreMetric); - } - }); - assertEquals(2, coreMetrics.size()); - coreMetrics.forEach( - metric -> { - assertEquals( - 1L, - ((Map) metric.get("QUERY./select.requestTimes")) - .get("count") - .longValue()); - minQueryTime[0] = - Math.min( - minQueryTime[0], - ((Map) metric.get("QUERY./select.requestTimes")) - .get("min_ms") - .doubleValue()); - maxQueryTime[0] = - Math.max( - maxQueryTime[0], - ((Map) metric.get("QUERY./select.requestTimes")) - .get("max_ms") - .doubleValue()); - assertEquals( - 1L, - ((Map) metric.get("UPDATE./update.requestTimes")) - .get("count") - .longValue()); - minUpdateTime[0] = - Math.min( - minUpdateTime[0], - ((Map) metric.get("UPDATE./update.requestTimes")) - .get("min_ms") - .doubleValue()); - maxUpdateTime[0] = - Math.max( - maxUpdateTime[0], - ((Map) metric.get("UPDATE./update.requestTimes")) - .get("max_ms") - .doubleValue()); - }); - - NamedList nodeMetrics = (NamedList) metrics.get("solr.node"); - assertEquals( - 2L, - ((Map) nodeMetrics.get("QUERY./select.requestTimes")) - .get("count") - .longValue()); - assertEquals( - minQueryTime[0], - ((Map) nodeMetrics.get("QUERY./select.requestTimes")) - .get("min_ms") - .doubleValue(), - 0.0); - assertEquals( - maxQueryTime[0], - ((Map) nodeMetrics.get("QUERY./select.requestTimes")) - .get("max_ms") - .doubleValue(), - 0.0); - assertEquals( - 2L, - ((Map) nodeMetrics.get("UPDATE./update.requestTimes")) - .get("count") - .longValue()); - assertEquals( - minUpdateTime[0], - ((Map) nodeMetrics.get("UPDATE./update.requestTimes")) - .get("min_ms") - .doubleValue(), - 0.0); - assertEquals( - maxUpdateTime[0], - ((Map) nodeMetrics.get("UPDATE./update.requestTimes")) - .get("max_ms") - .doubleValue(), - 0.0); + var coreContainer = cluster.getJettySolrRunners().get(0).getCoreContainer(); + SolrCore core1 = coreContainer.getCore(coreContainer.getAllCoreNames().get(0)); + SolrCore core2 = coreContainer.getCore(coreContainer.getAllCoreNames().get(1)); + + CounterSnapshot.CounterDataPointSnapshot actualCore1Selects = + SolrMetricTestUtils.newCloudSelectRequestsDatapoint(core1); + CounterSnapshot.CounterDataPointSnapshot actualCore1Updates = + SolrMetricTestUtils.newCloudUpdateRequestsDatapoint(core1); + CounterSnapshot.CounterDataPointSnapshot actualCore2Selects = + SolrMetricTestUtils.newCloudSelectRequestsDatapoint(core2); + CounterSnapshot.CounterDataPointSnapshot actualCore2Updates = + SolrMetricTestUtils.newCloudUpdateRequestsDatapoint(core2); + + assertEquals(1.0, actualCore1Selects.getValue(), 0.0); + assertEquals(1.0, actualCore1Updates.getValue(), 0.0); + assertEquals(1.0, actualCore2Updates.getValue(), 0.0); + assertEquals(1.0, actualCore2Selects.getValue(), 0.0); + + // Get node metrics and the select/update requests should be the sum of both cores requests + var nodeReader = SolrMetricTestUtils.getPrometheusMetricReader(coreContainer, "solr.node"); + + CounterSnapshot.CounterDataPointSnapshot nodeSelectRequests = + (CounterSnapshot.CounterDataPointSnapshot) + SolrMetricTestUtils.getDataPointSnapshot( + nodeReader, + "solr_node_requests", + Labels.builder() + .label("category", "QUERY") + .label("handler", "/select") + .label("otel_scope_name", "org.apache.solr") + .build()); + CounterSnapshot.CounterDataPointSnapshot nodeUpdateRequests = + (CounterSnapshot.CounterDataPointSnapshot) + SolrMetricTestUtils.getDataPointSnapshot( + nodeReader, + "solr_node_requests", + Labels.builder() + .label("category", "UPDATE") + .label("handler", "/update") + .label("otel_scope_name", "org.apache.solr") + .build()); + + assertNotNull("Node select requests should be recorded", nodeSelectRequests); + assertNotNull("Node update requests should be recorded", nodeUpdateRequests); + assertEquals(2.0, nodeSelectRequests.getValue(), 0.0); + assertEquals(2.0, nodeUpdateRequests.getValue(), 0.0); + + core1.close(); + core2.close(); } }