001package io.prometheus.client.hotspot; 002 003import io.prometheus.client.Collector; 004import io.prometheus.client.GaugeMetricFamily; 005 006import java.lang.management.ManagementFactory; 007import java.lang.reflect.InvocationTargetException; 008import java.lang.reflect.Method; 009import java.util.ArrayList; 010import java.util.Collections; 011import java.util.List; 012import java.util.logging.Logger; 013 014/** 015 * Exports metrics about JVM buffers. 016 * 017 * Can be replaced with a simple access once JDK 1.7 compatibility is baseline. 018 * 019 */ 020public class BufferPoolsExports extends Collector { 021 022 private static final Logger LOGGER = Logger.getLogger(BufferPoolsExports.class.getName()); 023 024 private final List<Object> bufferPoolMXBeans = new ArrayList<Object>(); 025 private Method getName; 026 private Method getMemoryUsed; 027 private Method getTotalCapacity; 028 private Method getCount; 029 030 public BufferPoolsExports() { 031 try { 032 final Class<?> bufferPoolMXBeanClass = Class.forName("java.lang.management.BufferPoolMXBean"); 033 bufferPoolMXBeans.addAll(accessBufferPoolMXBeans(bufferPoolMXBeanClass)); 034 035 getName = bufferPoolMXBeanClass.getMethod("getName"); 036 getMemoryUsed = bufferPoolMXBeanClass.getMethod("getMemoryUsed"); 037 getTotalCapacity = bufferPoolMXBeanClass.getMethod("getTotalCapacity"); 038 getCount = bufferPoolMXBeanClass.getMethod("getCount"); 039 040 } catch (ClassNotFoundException e) { 041 LOGGER.fine("BufferPoolMXBean not available, no metrics for buffer pools will be exported"); 042 } catch (NoSuchMethodException e) { 043 LOGGER.fine("Can not get necessary accessor from BufferPoolMXBean: " + e.getMessage()); 044 } 045 } 046 047 private static List<Object> accessBufferPoolMXBeans(final Class<?> bufferPoolMXBeanClass) { 048 try { 049 final Method getPlatformMXBeansMethod = ManagementFactory.class.getMethod("getPlatformMXBeans", Class.class); 050 final Object listOfBufferPoolMXBeanInstances = getPlatformMXBeansMethod.invoke(null, bufferPoolMXBeanClass); 051 052 return (List<Object>) listOfBufferPoolMXBeanInstances; 053 054 } catch (NoSuchMethodException e) { 055 LOGGER.fine("ManagementFactory.getPlatformMXBeans not available, no metrics for buffer pools will be exported"); 056 return Collections.emptyList(); 057 } catch (IllegalAccessException e) { 058 LOGGER.fine("ManagementFactory.getPlatformMXBeans not accessible, no metrics for buffer pools will be exported"); 059 return Collections.emptyList(); 060 } catch (InvocationTargetException e) { 061 LOGGER.warning("ManagementFactory.getPlatformMXBeans could not be invoked, no metrics for buffer pools will be exported"); 062 return Collections.emptyList(); 063 } 064 } 065 066 @Override 067 public List<MetricFamilySamples> collect() { 068 List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>(); 069 GaugeMetricFamily used = new GaugeMetricFamily( 070 "jvm_buffer_pool_used_bytes", 071 "Used bytes of a given JVM buffer pool.", 072 Collections.singletonList("pool")); 073 mfs.add(used); 074 GaugeMetricFamily capacity = new GaugeMetricFamily( 075 "jvm_buffer_pool_capacity_bytes", 076 "Bytes capacity of a given JVM buffer pool.", 077 Collections.singletonList("pool")); 078 mfs.add(capacity); 079 GaugeMetricFamily buffers = new GaugeMetricFamily( 080 "jvm_buffer_pool_used_buffers", 081 "Used buffers of a given JVM buffer pool.", 082 Collections.singletonList("pool")); 083 mfs.add(buffers); 084 for (final Object pool : bufferPoolMXBeans) { 085 used.addMetric( 086 Collections.singletonList(getName(pool)), 087 callLongMethond(getMemoryUsed,pool)); 088 capacity.addMetric( 089 Collections.singletonList(getName(pool)), 090 callLongMethond(getTotalCapacity,pool)); 091 buffers.addMetric( 092 Collections.singletonList(getName(pool)), 093 callLongMethond(getCount,pool)); 094 } 095 return mfs; 096 } 097 098 private long callLongMethond(final Method method, final Object pool) { 099 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}