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
076  void addMemoryPoolMetrics(List<MetricFamilySamples> sampleFamilies) {
077    GaugeMetricFamily used = new GaugeMetricFamily(
078        "jvm_memory_pool_bytes_used",
079        "Used bytes of a given JVM memory pool.",
080        Collections.singletonList("pool"));
081    sampleFamilies.add(used);
082    GaugeMetricFamily committed = new GaugeMetricFamily(
083        "jvm_memory_pool_bytes_committed",
084        "Committed bytes of a given JVM memory pool.",
085        Collections.singletonList("pool"));
086    sampleFamilies.add(committed);
087    GaugeMetricFamily max = new GaugeMetricFamily(
088        "jvm_memory_pool_bytes_max",
089        "Max bytes of a given JVM memory pool.",
090        Collections.singletonList("pool"));
091    sampleFamilies.add(max);
092    for (final MemoryPoolMXBean pool : poolBeans) {
093      MemoryUsage poolUsage = pool.getUsage();
094      used.addMetric(
095          Collections.singletonList(pool.getName()),
096          poolUsage.getUsed());
097      committed.addMetric(
098          Collections.singletonList(pool.getName()),
099          poolUsage.getCommitted());
100      max.addMetric(
101          Collections.singletonList(pool.getName()),
102          poolUsage.getMax());
103    }
104  }
105
106  public List<MetricFamilySamples> collect() {
107    List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>();
108    addMemoryAreaMetrics(mfs);
109    addMemoryPoolMetrics(mfs);
110    return mfs;
111  }
112}