Skip to content

Commit d7eef0f

Browse files
marcustbrian-brazil
authored andcommitted
Reflective version of #305 (#341)
1 parent 5b0a275 commit d7eef0f

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package io.prometheus.client.hotspot;
2+
3+
import io.prometheus.client.Collector;
4+
import io.prometheus.client.GaugeMetricFamily;
5+
6+
import java.lang.management.ManagementFactory;
7+
import java.lang.reflect.InvocationTargetException;
8+
import java.lang.reflect.Method;
9+
import java.util.ArrayList;
10+
import java.util.Collections;
11+
import java.util.List;
12+
import java.util.logging.Logger;
13+
14+
/**
15+
* Exports metrics about JVM buffers.
16+
*
17+
* Can be replaced with a simple access once JDK 1.7 compatibility is baseline.
18+
*
19+
*/
20+
public class BufferPoolsExports extends Collector {
21+
22+
private static final Logger LOGGER = Logger.getLogger(BufferPoolsExports.class.getName());
23+
24+
private final List<Object> bufferPoolMXBeans = new ArrayList<Object>();
25+
private Method getName;
26+
private Method getMemoryUsed;
27+
private Method getTotalCapacity;
28+
private Method getCount;
29+
30+
public BufferPoolsExports() {
31+
try {
32+
final Class<?> bufferPoolMXBeanClass = Class.forName("java.lang.management.BufferPoolMXBean");
33+
bufferPoolMXBeans.addAll(accessBufferPoolMXBeans(bufferPoolMXBeanClass));
34+
35+
getName = bufferPoolMXBeanClass.getMethod("getName");
36+
getMemoryUsed = bufferPoolMXBeanClass.getMethod("getMemoryUsed");
37+
getTotalCapacity = bufferPoolMXBeanClass.getMethod("getTotalCapacity");
38+
getCount = bufferPoolMXBeanClass.getMethod("getCount");
39+
40+
} catch (ClassNotFoundException e) {
41+
LOGGER.fine("BufferPoolMXBean not available, no metrics for buffer pools will be exported");
42+
} catch (NoSuchMethodException e) {
43+
LOGGER.fine("Can not get necessary accessor from BufferPoolMXBean: " + e.getMessage());
44+
}
45+
}
46+
47+
private static List<Object> accessBufferPoolMXBeans(final Class<?> bufferPoolMXBeanClass) {
48+
try {
49+
final Method getPlatformMXBeansMethod = ManagementFactory.class.getMethod("getPlatformMXBeans", Class.class);
50+
final Object listOfBufferPoolMXBeanInstances = getPlatformMXBeansMethod.invoke(null, bufferPoolMXBeanClass);
51+
52+
return (List<Object>) listOfBufferPoolMXBeanInstances;
53+
54+
} catch (NoSuchMethodException e) {
55+
LOGGER.fine("ManagementFactory.getPlatformMXBeans not available, no metrics for buffer pools will be exported");
56+
return Collections.emptyList();
57+
} catch (IllegalAccessException e) {
58+
LOGGER.fine("ManagementFactory.getPlatformMXBeans not accessible, no metrics for buffer pools will be exported");
59+
return Collections.emptyList();
60+
} catch (InvocationTargetException e) {
61+
LOGGER.warning("ManagementFactory.getPlatformMXBeans could not be invoked, no metrics for buffer pools will be exported");
62+
return Collections.emptyList();
63+
}
64+
}
65+
66+
@Override
67+
public List<MetricFamilySamples> collect() {
68+
List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>();
69+
GaugeMetricFamily used = new GaugeMetricFamily(
70+
"jvm_buffer_pool_used_bytes",
71+
"Used bytes of a given JVM buffer pool.",
72+
Collections.singletonList("pool"));
73+
mfs.add(used);
74+
GaugeMetricFamily capacity = new GaugeMetricFamily(
75+
"jvm_buffer_pool_capacity_bytes",
76+
"Bytes capacity of a given JVM buffer pool.",
77+
Collections.singletonList("pool"));
78+
mfs.add(capacity);
79+
GaugeMetricFamily buffers = new GaugeMetricFamily(
80+
"jvm_buffer_pool_used_buffers",
81+
"Used buffers of a given JVM buffer pool.",
82+
Collections.singletonList("pool"));
83+
mfs.add(buffers);
84+
for (final Object pool : bufferPoolMXBeans) {
85+
used.addMetric(
86+
Collections.singletonList(getName(pool)),
87+
callLongMethond(getMemoryUsed,pool));
88+
capacity.addMetric(
89+
Collections.singletonList(getName(pool)),
90+
callLongMethond(getTotalCapacity,pool));
91+
buffers.addMetric(
92+
Collections.singletonList(getName(pool)),
93+
callLongMethond(getCount,pool));
94+
}
95+
return mfs;
96+
}
97+
98+
private long callLongMethond(final Method method, final Object pool) {
99+
try {
100+
return (Long)method.invoke(pool);
101+
} catch (IllegalAccessException e) {
102+
LOGGER.fine("Couldn't call " + method.getName() + ": " + e.getMessage());
103+
} catch (InvocationTargetException e) {
104+
LOGGER.fine("Couldn't call " + method.getName() + ": " + e.getMessage());
105+
}
106+
return 0L;
107+
}
108+
109+
private String getName(final Object pool) {
110+
try {
111+
return (String)getName.invoke(pool);
112+
} catch (IllegalAccessException e) {
113+
LOGGER.fine("Couldn't call getName " + e.getMessage());
114+
} catch (InvocationTargetException e) {
115+
LOGGER.fine("Couldn't call getName " + e.getMessage());
116+
}
117+
return "<unknown>";
118+
}
119+
120+
121+
122+
}

simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public static synchronized void initialize() {
2222
if (!initialized) {
2323
new StandardExports().register();
2424
new MemoryPoolsExports().register();
25+
new BufferPoolsExports().register();
2526
new GarbageCollectorExports().register();
2627
new ThreadExports().register();
2728
new ClassLoadingExports().register();

0 commit comments

Comments
 (0)