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.management.MemoryMXBean;
008import java.lang.management.MemoryPoolMXBean;
009import java.lang.management.MemoryUsage;
010import java.util.ArrayList;
011import java.util.Collections;
012import java.util.List;
013
014/**
015 * Exports metrics about JVM memory areas.
016 * <p>
017 * Example usage:
018 * <pre>
019 * {@code
020 *   new MemoryPoolsExports().register();
021 * }
022 * </pre>
023 * Example metrics being exported:
024 * <pre>
025 *   jvm_memory_bytes_used{area="heap"} 2000000
026 *   jvm_memory_bytes_committed{area="nonheap"} 200000
027 *   jvm_memory_bytes_max{area="nonheap"} 2000000
028 *   jvm_memory_pool_bytes_used{pool="PS Eden Space"} 2000
029 * </pre>
030 */
031public class MemoryPoolsExports extends Collector {
032  private final MemoryMXBean memoryBean;
033  private final List<MemoryPoolMXBean> poolBeans;
034
035  public MemoryPoolsExports() {
036    this(
037        ManagementFactory.getMemoryMXBean(),
038        ManagementFactory.getMemoryPoolMXBeans());
039  }
040
041  public MemoryPoolsExports(MemoryMXBean memoryBean,
042                             List<MemoryPoolMXBean> poolBeans) {
043    this.memoryBean = memoryBean;
044    this.poolBeans = poolBeans;
045  }
046
047  void addMemoryAreaMetrics(List<MetricFamilySamples> sampleFamilies) {
048    MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
049    MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
050
051    GaugeMetricFamily used = new GaugeMetricFamily(
052        "jvm_memory_bytes_used",
053        "Used bytes of a given JVM memory area.",
054        Collections.singletonList("area"));
055    used.addMetric(Collections.singletonList("heap"), heapUsage.getUsed());
056    used.addMetric(Collections.singletonList("nonheap"), nonHeapUsage.getUsed());
057    sampleFamilies.add(used);
058
059    GaugeMetricFamily committed = new GaugeMetricFamily(
060        "jvm_memory_bytes_committed",
061        "Committed (bytes) of a given JVM memory area.",
062        Collections.singletonList("area"));
063    committed.addMetric(Collections.singletonList("heap"), heapUsage.getCommitted());
064    committed.addMetric(Collections.singletonList("nonheap"), nonHeapUsage.getCommitted());
065    sampleFamilies.add(committed);
066
067    GaugeMetricFamily max = new GaugeMetricFamily(
068        "jvm_memory_bytes_max",
069        "Max (bytes) of a given JVM memory area.",
070        Collections.singletonList("area"));
071    max.addMetric(Collections.singletonList("heap"), heapUsage.getMax());
072    max.addMetric(Collections.singletonList("nonheap"), nonHeapUsage.getMax());
073    sampleFamilies.add(max);
074
075    GaugeMetricFamily init = new GaugeMetricFamily(
076        "jvm_memory_bytes_init",
077        "Initial bytes of a given JVM memory area.",
078        Collections.singletonList("area"));
079    init.addMetric(Collections.singletonList("heap"), heapUsage.getInit());
080    init.addMetric(Collections.singletonList("nonheap"), nonHeapUsage.getInit());
081    sampleFamilies.add(init);
082  }
083
084  void addMemoryPoolMetrics(List<MetricFamilySamples> sampleFamilies) {
085    GaugeMetricFamily used = new GaugeMetricFamily(
086        "jvm_memory_pool_bytes_used",
087        "Used bytes of a given JVM memory pool.",
088        Collections.singletonList("pool"));
089    sampleFamilies.add(used);
090    GaugeMetricFamily committed = new GaugeMetricFamily(
091        "jvm_memory_pool_bytes_committed",
092        "Committed bytes of a given JVM memory pool.",
093        Collections.singletonList("pool"));
094    sampleFamilies.add(committed);
095    GaugeMetricFamily max = new GaugeMetricFamily(
096        "jvm_memory_pool_bytes_max",
097        "Max bytes of a given JVM memory pool.",
098        Collections.singletonList("pool"));
099    sampleFamilies.add(max);
100    GaugeMetricFamily init = new GaugeMetricFamily(
101        "jvm_memory_pool_bytes_init",
102        "Initial bytes of a given JVM memory pool.",
103        Collections.singletonList("pool"));
104    sampleFamilies.add(init);
105    for (final MemoryPoolMXBean pool : poolBeans) {
106      MemoryUsage poolUsage = pool.getUsage();
107      used.addMetric(
108          Collections.singletonList(pool.getName()),
109          poolUsage.getUsed());
110      committed.addMetric(
111          Collections.singletonList(pool.getName()),
112          poolUsage.getCommitted());
113      max.addMetric(
114          Collections.singletonList(pool.getName()),
115          poolUsage.getMax());
116      init.addMetric(
117          Collections.singletonList(pool.getName()),
118          poolUsage.getInit());
119    }
120  }
121
122  public List<MetricFamilySamples> collect() {
123    List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>();
124    addMemoryAreaMetrics(mfs);
125    addMemoryPoolMetrics(mfs);
126    return mfs;
127  }
128}