You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by yo...@apache.org on 2022/07/29 10:38:33 UTC

[bookkeeper] branch master updated: [ISSUE 2637] Fix jvm_memory_direct_bytes_used metrics when using jdk11+ (#3252)

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

yong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new cefe9d44da [ISSUE 2637] Fix jvm_memory_direct_bytes_used metrics when using jdk11+ (#3252)
cefe9d44da is described below

commit cefe9d44dad3558cd4cc30547007c3c41b9bfbec
Author: ZhangJian He <sh...@gmail.com>
AuthorDate: Fri Jul 29 18:38:27 2022 +0800

    [ISSUE 2637] Fix jvm_memory_direct_bytes_used metrics when using jdk11+ (#3252)
    
    Fix #2637 #3247
    
    ### Motivation
    The mertics about `jvm_memory_direct_bytes_used` is acquired by netty's `PlatformDependent#DIRECT_MEMORY_COUNTER`. Which can only acquired the memory used by netty.
    
    ### Changes
    - use `java.nio.Bits#RESERVED_MEMORY` for jvm direct memory metrics.
    - add tests to ensure `jvm_memory_direct_bytes_max` and `jvm_memory_direct_bytes_used` gets value.
---
 .../prometheus/PrometheusMetricsProvider.java      | 30 ++++++----------
 .../prometheus/TestPrometheusMetricsProvider.java  | 40 ++++++++++++++++++++++
 2 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/stats/bookkeeper-stats-providers/prometheus-metrics-provider/src/main/java/org/apache/bookkeeper/stats/prometheus/PrometheusMetricsProvider.java b/stats/bookkeeper-stats-providers/prometheus-metrics-provider/src/main/java/org/apache/bookkeeper/stats/prometheus/PrometheusMetricsProvider.java
index 4586c7110c..1083527218 100644
--- a/stats/bookkeeper-stats-providers/prometheus-metrics-provider/src/main/java/org/apache/bookkeeper/stats/prometheus/PrometheusMetricsProvider.java
+++ b/stats/bookkeeper-stats-providers/prometheus-metrics-provider/src/main/java/org/apache/bookkeeper/stats/prometheus/PrometheusMetricsProvider.java
@@ -30,19 +30,19 @@ import io.prometheus.client.hotspot.GarbageCollectorExports;
 import io.prometheus.client.hotspot.MemoryPoolsExports;
 import io.prometheus.client.hotspot.StandardExports;
 import io.prometheus.client.hotspot.ThreadExports;
-
 import java.io.IOException;
 import java.io.Writer;
-import java.lang.reflect.Field;
+import java.lang.management.BufferPoolMXBean;
+import java.lang.management.ManagementFactory;
 import java.net.InetSocketAddress;
 import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
 import org.apache.bookkeeper.stats.StatsLogger;
 import org.apache.bookkeeper.stats.StatsProvider;
 import org.apache.bookkeeper.stats.ThreadRegistry;
@@ -130,7 +130,7 @@ public class PrometheusMetricsProvider implements StatsProvider {
         registerMetrics(Gauge.build("jvm_memory_direct_bytes_used", "-").create().setChild(new Child() {
             @Override
             public double get() {
-                return directMemoryUsage != null ? directMemoryUsage.longValue() : Double.NaN;
+                return poolMxBeanOp.isPresent() ? poolMxBeanOp.get().getMemoryUsed() : Double.NaN;
             }
         }));
 
@@ -215,21 +215,11 @@ public class PrometheusMetricsProvider implements StatsProvider {
 
     private static final Logger log = LoggerFactory.getLogger(PrometheusMetricsProvider.class);
 
-    /*
-     * Try to get Netty counter of used direct memory. This will be correct, unlike the JVM values.
-     */
-    private static final AtomicLong directMemoryUsage;
-    static {
-        AtomicLong tmpDirectMemoryUsage = null;
+    private static final Optional<BufferPoolMXBean> poolMxBeanOp;
 
-        try {
-            Field field = PlatformDependent.class.getDeclaredField("DIRECT_MEMORY_COUNTER");
-            field.setAccessible(true);
-            tmpDirectMemoryUsage = (AtomicLong) field.get(null);
-        } catch (Throwable t) {
-            log.warn("Failed to access netty DIRECT_MEMORY_COUNTER field {}", t.getMessage());
-        }
-
-        directMemoryUsage = tmpDirectMemoryUsage;
+    static {
+        List<BufferPoolMXBean> platformMXBeans = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
+        poolMxBeanOp = platformMXBeans.stream()
+                .filter(bufferPoolMXBean -> bufferPoolMXBean.getName().equals("direct")).findAny();
     }
 }
diff --git a/stats/bookkeeper-stats-providers/prometheus-metrics-provider/src/test/java/org/apache/bookkeeper/stats/prometheus/TestPrometheusMetricsProvider.java b/stats/bookkeeper-stats-providers/prometheus-metrics-provider/src/test/java/org/apache/bookkeeper/stats/prometheus/TestPrometheusMetricsProvider.java
index df954e64d9..999be26cbb 100644
--- a/stats/bookkeeper-stats-providers/prometheus-metrics-provider/src/test/java/org/apache/bookkeeper/stats/prometheus/TestPrometheusMetricsProvider.java
+++ b/stats/bookkeeper-stats-providers/prometheus-metrics-provider/src/test/java/org/apache/bookkeeper/stats/prometheus/TestPrometheusMetricsProvider.java
@@ -21,11 +21,16 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
 import java.util.Collections;
+import java.util.HashMap;
+
 import lombok.Cleanup;
 import org.apache.bookkeeper.stats.Counter;
 import org.apache.bookkeeper.stats.StatsLogger;
 import org.apache.commons.configuration.PropertiesConfiguration;
+import org.junit.Assert;
 import org.junit.Test;
 
 /**
@@ -111,4 +116,39 @@ public class TestPrometheusMetricsProvider {
         assertEquals(1, provider.counters.size());
     }
 
+    @Test
+    public void testJvmDirectMemoryMetrics() throws Exception {
+        PropertiesConfiguration config = new PropertiesConfiguration();
+        config.setProperty(PrometheusMetricsProvider.PROMETHEUS_STATS_HTTP_ENABLE, true);
+        config.setProperty(PrometheusMetricsProvider.PROMETHEUS_STATS_HTTP_PORT, 0);
+        config.setProperty(PrometheusMetricsProvider.PROMETHEUS_STATS_HTTP_ADDRESS, "127.0.0.1");
+        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(25);
+        PrometheusMetricsProvider provider = new PrometheusMetricsProvider();
+        try {
+            provider.start(config);
+            assertNotNull(provider.server);
+            StringWriter writer = new StringWriter();
+            provider.writeAllMetrics(writer);
+            String s = writer.toString();
+            String[] split = s.split(System.lineSeparator());
+            HashMap<String, String> map = new HashMap<>();
+            for (String str : split) {
+                String[] aux = str.split(" ");
+                map.put(aux[0], aux[1]);
+            }
+            String directBytesMax = map.get("jvm_memory_direct_bytes_max{}");
+            Assert.assertNotNull(directBytesMax);
+            Assert.assertNotEquals("Nan", directBytesMax);
+            Assert.assertNotEquals("-1", directBytesMax);
+            String directBytesUsed = map.get("jvm_memory_direct_bytes_used{}");
+            Assert.assertNotNull(directBytesUsed);
+            Assert.assertNotEquals("Nan", directBytesUsed);
+            Assert.assertTrue(Double.parseDouble(directBytesUsed) > 25);
+            // ensure byteBuffer doesn't gc
+            byteBuffer.clear();
+        } finally {
+            provider.stop();
+        }
+    }
+
 }