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