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();
+ }
+ }
+
}