diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/BufferPoolsExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/BufferPoolsExports.java new file mode 100644 index 000000000..6ff7d522b --- /dev/null +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/BufferPoolsExports.java @@ -0,0 +1,71 @@ +package io.prometheus.client.hotspot; + +import io.prometheus.client.Collector; +import io.prometheus.client.CounterMetricFamily; +import io.prometheus.client.GaugeMetricFamily; + +import java.lang.management.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Exports metrics about JVM buffer pools. + *

+ * Example usage: + *

+ * {@code
+ *   new BufferPoolsExports().register();
+ * }
+ * 
+ * Example metrics being exported: + *
+ *   jvm_buffer_pool_bytes_used{name="direct"} 2000000
+ *   jvm_buffer_pool_bytes_capacity{name="direct"} 200000
+ *   jvm_buffer_pool_count{name="nonheap"} 20
+ * 
+ */ +public class BufferPoolsExports extends Collector { + private final List poolBeans; + + public BufferPoolsExports() { + this(ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class)); + } + + public BufferPoolsExports(List poolBeans) { + this.poolBeans = poolBeans; + } + + void addBufferPoolMetrics(List sampleFamilies) { + GaugeMetricFamily used = new GaugeMetricFamily( + "jvm_buffer_pool_bytes_used", + "Estimate of the memory (bytes) that the Java virtual machine is using for this buffer pool.", + Collections.singletonList("name")); + + GaugeMetricFamily capacity = new GaugeMetricFamily( + "jvm_buffer_pool_bytes_capacity", + "Estimate of the total capacity (bytes) of the buffers in this pool.", + Collections.singletonList("name")); + + CounterMetricFamily count = new CounterMetricFamily( + "jvm_buffer_pool_count", + "Estimate of the number of buffers in the pool", + Collections.singletonList("name")); + + for (BufferPoolMXBean poolBean : this.poolBeans) { + used.addMetric(Collections.singletonList(poolBean.getName()), poolBean.getMemoryUsed()); + capacity.addMetric(Collections.singletonList(poolBean.getName()), poolBean.getTotalCapacity()); + count.addMetric(Collections.singletonList(poolBean.getName()), poolBean.getCount()); + } + + sampleFamilies.add(used); + sampleFamilies.add(capacity); + sampleFamilies.add(count); + } + + public List collect() { + List mfs = new ArrayList(); + addBufferPoolMetrics(mfs); + return mfs; + } +} diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java index 371110e13..bab982b08 100644 --- a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java @@ -26,6 +26,7 @@ public static synchronized void initialize() { new ThreadExports().register(); new ClassLoadingExports().register(); new VersionInfoExports().register(); + new BufferPoolsExports().register(); initialized = true; } } diff --git a/simpleclient_hotspot/src/test/java/io/prometheus/client/hotspot/BufferPoolsExportsTest.java b/simpleclient_hotspot/src/test/java/io/prometheus/client/hotspot/BufferPoolsExportsTest.java new file mode 100644 index 000000000..48893a1fb --- /dev/null +++ b/simpleclient_hotspot/src/test/java/io/prometheus/client/hotspot/BufferPoolsExportsTest.java @@ -0,0 +1,81 @@ +package io.prometheus.client.hotspot; + +import io.prometheus.client.CollectorRegistry; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.lang.management.BufferPoolMXBean; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +public class BufferPoolsExportsTest { + + private BufferPoolMXBean mockPoolsBean1 = Mockito.mock(BufferPoolMXBean.class); + private BufferPoolMXBean mockPoolsBean2 = Mockito.mock(BufferPoolMXBean.class); + private List mockList = Arrays.asList(mockPoolsBean1, mockPoolsBean2); + private CollectorRegistry registry = new CollectorRegistry(); + private BufferPoolsExports collectorUnderTest; + + @Before + public void setUp() { + when(mockPoolsBean1.getName()).thenReturn("direct"); + when(mockPoolsBean1.getTotalCapacity()).thenReturn(200000L); + when(mockPoolsBean1.getMemoryUsed()).thenReturn(100000L); + when(mockPoolsBean1.getCount()).thenReturn(3L); + when(mockPoolsBean2.getName()).thenReturn("mapped"); + when(mockPoolsBean2.getTotalCapacity()).thenReturn(0L); + when(mockPoolsBean2.getMemoryUsed()).thenReturn(0L); + when(mockPoolsBean2.getCount()).thenReturn(0L); + collectorUnderTest = new BufferPoolsExports(mockList).register(registry); + } + + @Test + public void testMemoryPools() { + assertEquals( + 100000L, + registry.getSampleValue( + "jvm_buffer_pool_bytes_used", + new String[]{"name"}, + new String[]{"direct"}), + .0000001); + assertEquals( + 200000L, + registry.getSampleValue( + "jvm_buffer_pool_bytes_capacity", + new String[]{"name"}, + new String[]{"direct"}), + .0000001); + assertEquals( + 3L, + registry.getSampleValue( + "jvm_buffer_pool_count", + new String[]{"name"}, + new String[]{"direct"}), + .0000001); + assertEquals( + 0L, + registry.getSampleValue( + "jvm_buffer_pool_bytes_used", + new String[]{"name"}, + new String[]{"mapped"}), + .0000001); + assertEquals( + 0L, + registry.getSampleValue( + "jvm_buffer_pool_bytes_capacity", + new String[]{"name"}, + new String[]{"mapped"}), + .0000001); + assertEquals( + 0L, + registry.getSampleValue( + "jvm_buffer_pool_count", + new String[]{"name"}, + new String[]{"mapped"}), + .0000001); + } +}