001package io.prometheus.metrics.instrumentation.jvm; 002 003import io.prometheus.metrics.config.PrometheusProperties; 004import io.prometheus.metrics.core.metrics.GaugeWithCallback; 005import io.prometheus.metrics.model.registry.PrometheusRegistry; 006import io.prometheus.metrics.model.snapshots.Unit; 007import java.lang.management.BufferPoolMXBean; 008import java.lang.management.ManagementFactory; 009import java.util.List; 010import javax.annotation.Nullable; 011 012/** 013 * JVM Buffer Pool metrics. The {@link JvmBufferPoolMetrics} are registered as part of the {@link 014 * JvmMetrics} like this: 015 * 016 * <pre>{@code 017 * JvmMetrics.builder().register(); 018 * }</pre> 019 * 020 * However, if you want only the {@link JvmBufferPoolMetrics} you can also register them directly: 021 * 022 * <pre>{@code 023 * JvmBufferPoolMetrics.builder().register(); 024 * }</pre> 025 * 026 * Example metrics being exported: 027 * 028 * <pre> 029 * # HELP jvm_buffer_pool_capacity_bytes Bytes capacity of a given JVM buffer pool. 030 * # TYPE jvm_buffer_pool_capacity_bytes gauge 031 * jvm_buffer_pool_capacity_bytes{pool="direct"} 8192.0 032 * jvm_buffer_pool_capacity_bytes{pool="mapped"} 0.0 033 * # HELP jvm_buffer_pool_used_buffers Used buffers of a given JVM buffer pool. 034 * # TYPE jvm_buffer_pool_used_buffers gauge 035 * jvm_buffer_pool_used_buffers{pool="direct"} 1.0 036 * jvm_buffer_pool_used_buffers{pool="mapped"} 0.0 037 * # HELP jvm_buffer_pool_used_bytes Used bytes of a given JVM buffer pool. 038 * # TYPE jvm_buffer_pool_used_bytes gauge 039 * jvm_buffer_pool_used_bytes{pool="direct"} 8192.0 040 * jvm_buffer_pool_used_bytes{pool="mapped"} 0.0 041 * </pre> 042 */ 043public class JvmBufferPoolMetrics { 044 045 private static final String JVM_BUFFER_POOL_USED_BYTES = "jvm_buffer_pool_used_bytes"; 046 private static final String JVM_BUFFER_POOL_CAPACITY_BYTES = "jvm_buffer_pool_capacity_bytes"; 047 private static final String JVM_BUFFER_POOL_USED_BUFFERS = "jvm_buffer_pool_used_buffers"; 048 049 private final PrometheusProperties config; 050 private final List<BufferPoolMXBean> bufferPoolBeans; 051 052 private JvmBufferPoolMetrics( 053 List<BufferPoolMXBean> bufferPoolBeans, PrometheusProperties config) { 054 this.config = config; 055 this.bufferPoolBeans = bufferPoolBeans; 056 } 057 058 private void register(PrometheusRegistry registry) { 059 060 GaugeWithCallback.builder(config) 061 .name(JVM_BUFFER_POOL_USED_BYTES) 062 .help("Used bytes of a given JVM buffer pool.") 063 .unit(Unit.BYTES) 064 .labelNames("pool") 065 .callback( 066 callback -> { 067 for (BufferPoolMXBean pool : bufferPoolBeans) { 068 callback.call(pool.getMemoryUsed(), pool.getName()); 069 } 070 }) 071 .register(registry); 072 073 GaugeWithCallback.builder(config) 074 .name(JVM_BUFFER_POOL_CAPACITY_BYTES) 075 .help("Bytes capacity of a given JVM buffer pool.") 076 .unit(Unit.BYTES) 077 .labelNames("pool") 078 .callback( 079 callback -> { 080 for (BufferPoolMXBean pool : bufferPoolBeans) { 081 callback.call(pool.getTotalCapacity(), pool.getName()); 082 } 083 }) 084 .register(registry); 085 086 GaugeWithCallback.builder(config) 087 .name(JVM_BUFFER_POOL_USED_BUFFERS) 088 .help("Used buffers of a given JVM buffer pool.") 089 .labelNames("pool") 090 .callback( 091 callback -> { 092 for (BufferPoolMXBean pool : bufferPoolBeans) { 093 callback.call(pool.getCount(), pool.getName()); 094 } 095 }) 096 .register(registry); 097 } 098 099 public static Builder builder() { 100 return new Builder(PrometheusProperties.get()); 101 } 102 103 public static Builder builder(PrometheusProperties config) { 104 return new Builder(config); 105 } 106 107 public static class Builder { 108 109 private final PrometheusProperties config; 110 @Nullable private List<BufferPoolMXBean> bufferPoolBeans; 111 112 private Builder(PrometheusProperties config) { 113 this.config = config; 114 } 115 116 /** Package private. For testing only. */ 117 Builder bufferPoolBeans(List<BufferPoolMXBean> bufferPoolBeans) { 118 this.bufferPoolBeans = bufferPoolBeans; 119 return this; 120 } 121 122 public void register() { 123 register(PrometheusRegistry.defaultRegistry); 124 } 125 126 public void register(PrometheusRegistry registry) { 127 List<BufferPoolMXBean> bufferPoolBeans = this.bufferPoolBeans; 128 if (bufferPoolBeans == null) { 129 bufferPoolBeans = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); 130 } 131 new JvmBufferPoolMetrics(bufferPoolBeans, config).register(registry); 132 } 133 } 134}