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}