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

dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 319b70d24b3b797387be0ee81afd7359648ce1e0
Author: Jan Høydahl <[email protected]>
AuthorDate: Fri Aug 7 19:37:45 2026 +0200

    Fix consumers of JVM CPU metrics renamed by OTel Prometheus exporter update 
(#4711)
    
    This also fixes the PlacementPluginIntegrationTest.testAttributeFetcherImpl 
test failures
    
    (cherry picked from commit 6f0d0b5b7295611acf7c3d95030530b415a4b965)
---
 .../fix-jvm-cpu-utilization-metric-name.yml        | 10 +++++
 .../cluster/placement/impl/NodeMetricImpl.java     |  2 +-
 .../util/circuitbreaker/CPUCircuitBreaker.java     |  2 +-
 .../org/apache/solr/util/TestCircuitBreakers.java  | 48 ++++++++++++++++++++++
 .../pages/major-changes-in-solr-10.adoc            |  3 ++
 .../solr/client/solrj/impl/NodeValueFetcher.java   |  2 +-
 6 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/changelog/unreleased/fix-jvm-cpu-utilization-metric-name.yml 
b/changelog/unreleased/fix-jvm-cpu-utilization-metric-name.yml
new file mode 100644
index 00000000000..1c329ff841d
--- /dev/null
+++ b/changelog/unreleased/fix-jvm-cpu-utilization-metric-name.yml
@@ -0,0 +1,10 @@
+title: >
+  The Prometheus JVM CPU metrics are now named `jvm_system_cpu_utilization` and
+  `jvm_cpu_recent_utilization` (the `_ratio` suffix was dropped) following the
+  OpenTelemetry Prometheus exporter update.
+type: changed
+authors:
+  - name: Jan Høydahl
+links:
+  - name: PR#4711
+    url: https://github.com/apache/solr/pull/4711
diff --git 
a/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java 
b/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
index 4f76896a320..96ba2d1b676 100644
--- 
a/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
+++ 
b/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
@@ -38,7 +38,7 @@ public class NodeMetricImpl<T> extends MetricImpl<T> 
implements NodeMetric<T> {
 
   /** System load average. */
   public static final NodeMetricImpl<Double> SYSLOAD_AVG =
-      new NodeMetricImpl<>("sysLoadAvg", "jvm_system_cpu_utilization_ratio");
+      new NodeMetricImpl<>("sysLoadAvg", "jvm_system_cpu_utilization");
 
   /** Number of available processors. */
   public static final NodeMetricImpl<Integer> AVAILABLE_PROCESSORS =
diff --git 
a/solr/core/src/java/org/apache/solr/util/circuitbreaker/CPUCircuitBreaker.java 
b/solr/core/src/java/org/apache/solr/util/circuitbreaker/CPUCircuitBreaker.java
index 09248363bcd..391f88049dc 100644
--- 
a/solr/core/src/java/org/apache/solr/util/circuitbreaker/CPUCircuitBreaker.java
+++ 
b/solr/core/src/java/org/apache/solr/util/circuitbreaker/CPUCircuitBreaker.java
@@ -112,7 +112,7 @@ public class CPUCircuitBreaker extends CircuitBreaker 
implements SolrCoreAware {
     return this.cc
         .getMetricManager()
         .getPrometheusMetricReader("solr.jvm")
-        .collect(name -> name.contains("jvm_system_cpu_utilization_ratio"))
+        .collect(name -> name.contains("jvm_system_cpu_utilization"))
         .stream()
         .filter(GaugeSnapshot.class::isInstance)
         .map(GaugeSnapshot.class::cast)
diff --git a/solr/core/src/test/org/apache/solr/util/TestCircuitBreakers.java 
b/solr/core/src/test/org/apache/solr/util/TestCircuitBreakers.java
index 648ac035854..88bdee78087 100644
--- a/solr/core/src/test/org/apache/solr/util/TestCircuitBreakers.java
+++ b/solr/core/src/test/org/apache/solr/util/TestCircuitBreakers.java
@@ -19,8 +19,10 @@ package org.apache.solr.util;
 
 import static org.hamcrest.CoreMatchers.containsString;
 
+import com.sun.management.OperatingSystemMXBean;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
+import java.lang.management.ManagementFactory;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
@@ -30,6 +32,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
+import org.apache.lucene.util.SuppressForbidden;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.common.SolrException;
@@ -43,6 +46,7 @@ import 
org.apache.solr.util.circuitbreaker.CircuitBreakerRegistry;
 import org.apache.solr.util.circuitbreaker.LoadAverageCircuitBreaker;
 import org.apache.solr.util.circuitbreaker.MemoryCircuitBreaker;
 import org.junit.After;
+import org.junit.Assume;
 import org.junit.BeforeClass;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -271,6 +275,39 @@ public class TestCircuitBreakers extends SolrTestCaseJ4 {
     assertThatHighQueryLoadTrips(circuitBreaker, 5);
   }
 
+  /**
+   * Reads a real CPU usage value from the metrics, guarding against a 
regression where a renamed
+   * JVM metric made {@link CPUCircuitBreaker#calculateLiveCPUUsage()} 
silently return -1. Gated by
+   * an independent native-CPU probe so that a name regression fails here 
rather than being mistaken
+   * for an unsupported machine (both otherwise yield -1).
+   */
+  public void testCPUCircuitBreakerReadsLiveUsage() {
+    Assume.assumeTrue("No native CPU measurement on this machine", 
nativeCpuMeasurementSupported());
+
+    double usage = new 
ExposedCPUCircuitBreaker(h.getCoreContainer()).liveCPUUsage();
+    assertTrue("Expected CPU usage >= 0 but got " + usage, usage >= 0);
+  }
+
+  @SuppressForbidden(reason = "Probing com.sun OperatingSystemMXBean for 
native CPU support")
+  private static boolean nativeCpuMeasurementSupported() {
+    if (!(ManagementFactory.getOperatingSystemMXBean() instanceof 
OperatingSystemMXBean osBean)) {
+      return false;
+    }
+    // getCpuLoad() needs two samples and may return a negative value on the 
first calls
+    for (int i = 0; i < 10; i++) {
+      if (osBean.getCpuLoad() >= 0) {
+        return true;
+      }
+      try {
+        Thread.sleep(50);
+      } catch (InterruptedException e) {
+        Thread.currentThread().interrupt();
+        return false;
+      }
+    }
+    return false;
+  }
+
   /**
    * Common assert method to be reused in tests
    *
@@ -441,6 +478,17 @@ public class TestCircuitBreakers extends SolrTestCaseJ4 {
     }
   }
 
+  /** Exposes the real (protected) CPU usage calculation for testing. */
+  private static class ExposedCPUCircuitBreaker extends CPUCircuitBreaker {
+    public ExposedCPUCircuitBreaker(CoreContainer coreContainer) {
+      super(coreContainer);
+    }
+
+    double liveCPUUsage() {
+      return calculateLiveCPUUsage();
+    }
+  }
+
   private static class FakeLoadAverageCircuitBreaker extends 
LoadAverageCircuitBreaker {
     @Override
     protected double calculateLiveLoadAverage() {
diff --git 
a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc 
b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
index 80acfeae06a..7b4a5e9e452 100644
--- 
a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
+++ 
b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
@@ -412,6 +412,9 @@ Users who consume Solr metrics via OTLP and rely on the 
10.0 underscore-format n
   (e.g., `crossdc.consumer.output.total` → 
`solr.crossdc.consumer.output.total`)
 * All CrossDC producer metrics have been renamed: 
`solr.core.crossdc.producer.*` → `solr.crossdc.producer.*`
   (e.g., `solr.core.crossdc.producer.submitted` → 
`solr.crossdc.producer.submitted`)
+* The Prometheus JVM CPU utilization metrics lost their `_ratio` suffix, as 
the updated OpenTelemetry
+  exporter no longer maps the OTel unit `1` to a `_ratio` suffix: 
`jvm_system_cpu_utilization_ratio` →
+  `jvm_system_cpu_utilization` and `jvm_cpu_recent_utilization_ratio` → 
`jvm_cpu_recent_utilization`.
 
 Update your dashboards or other metrics consumers accordingly.
 
diff --git 
a/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/NodeValueFetcher.java
 
b/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/NodeValueFetcher.java
index 3dd91fca5d3..abd31c5d86c 100644
--- 
a/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/NodeValueFetcher.java
+++ 
b/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/NodeValueFetcher.java
@@ -74,7 +74,7 @@ public class NodeValueFetcher {
             .sum();
       }
     },
-    SYSLOADAVG("sysLoadAvg", "jvm_system_cpu_utilization_ratio");
+    SYSLOADAVG("sysLoadAvg", "jvm_system_cpu_utilization");
 
     public final String tagName;
     public final String metricName;

Reply via email to