001package io.prometheus.client.hotspot;
002
003import io.prometheus.client.Collector;
004
005import java.lang.management.ManagementFactory;
006import java.lang.management.MemoryMXBean;
007import java.lang.management.MemoryPoolMXBean;
008import java.lang.management.MemoryUsage;
009import java.util.ArrayList;
010import java.util.Arrays;
011import java.util.HashMap;
012import java.util.List;
013import java.util.regex.Pattern;
014
015/**
016 * Exports metrics about JVM memory areas.
017 * <p>
018 * Example usage:
019 * <pre>
020 * {@code
021 *   new MemoryPoolsExports().register();
022 * }
023 * </pre>
024 * Example metrics being exported:
025 * <pre>
026 *   jvm_memory_bytes_used{area="heap"} 2000000
027 *   jvm_memory_bytes_committed{area="nonheap"} 200000
028 *   jvm_memory_bytes_max{area="nonheap"} 2000000
029 *   jvm_memory_pool_bytes_used{pool="PS Eden Space"} 2000
030 * </pre>
031 */
032public class MemoryPoolsExports extends Collector {
033  private final MemoryMXBean memoryBean;
034  private final List<MemoryPoolMXBean> poolBeans;
035
036  public MemoryPoolsExports() {
037    this(
038        ManagementFactory.getMemoryMXBean(),
039        ManagementFactory.getMemoryPoolMXBeans());
040  }
041
042  public MemoryPoolsExports(MemoryMXBean memoryBean,
043                             List<MemoryPoolMXBean> poolBeans) {
044    this.memoryBean = memoryBean;
045    this.poolBeans = poolBeans;
046  }
047
048  void addMemoryAreaMetrics(List<MetricFamilySamples> sampleFamilies) {
049    MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
050    MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
051    ArrayList<MetricFamilySamples.Sample> usedSamples = new ArrayList<MetricFamilySamples.Sample>();
052    usedSamples.add(
053        new MetricFamilySamples.Sample(
054            "jvm_memory_bytes_used",
055            Arrays.asList("area"),
056            Arrays.asList("heap"),
057            heapUsage.getUsed()));
058    usedSamples.add(
059        new MetricFamilySamples.Sample(
060            "jvm_memory_bytes_used",
061            Arrays.asList("area"),
062            Arrays.asList("nonheap"),
063            nonHeapUsage.getUsed()));
064    sampleFamilies.add(
065        new MetricFamilySamples(
066            "jvm_memory_bytes_used",
067            Type.GAUGE,
068            "Used bytes of a given JVM memory area.",
069            usedSamples));
070    ArrayList<MetricFamilySamples.Sample> committedSamples = new ArrayList<MetricFamilySamples.Sample>();
071    committedSamples.add(
072        new MetricFamilySamples.Sample(
073            "jvm_memory_bytes_committed",
074            Arrays.asList("area"),
075            Arrays.asList("heap"),
076            heapUsage.getCommitted()));
077    committedSamples.add(
078        new MetricFamilySamples.Sample(
079            "jvm_memory_bytes_committed",
080            Arrays.asList("area"),
081            Arrays.asList("nonheap"),
082            nonHeapUsage.getCommitted()));
083    sampleFamilies.add(
084        new MetricFamilySamples(
085            "jvm_memory_bytes_committed",
086            Type.GAUGE,
087            "Committed (bytes) of a given JVM memory area.",
088            committedSamples));
089    ArrayList<MetricFamilySamples.Sample> maxSamples = new ArrayList<MetricFamilySamples.Sample>();
090    maxSamples.add(
091        new MetricFamilySamples.Sample(
092            "jvm_memory_bytes_max",
093            Arrays.asList("area"),
094            Arrays.asList("heap"),
095            heapUsage.getMax()));
096    maxSamples.add(
097        new MetricFamilySamples.Sample(
098            "jvm_memory_bytes_max",
099            Arrays.asList("area"),
100            Arrays.asList("nonheap"),
101            nonHeapUsage.getMax()));
102    sampleFamilies.add(
103        new MetricFamilySamples(
104            "jvm_memory_bytes_max",
105            Type.GAUGE,
106            "Maximum (bytes) of a given JVM memory area.",
107            maxSamples));
108  }
109
110  void addMemoryPoolMetrics(List<MetricFamilySamples> sampleFamilies) {
111    ArrayList<MetricFamilySamples.Sample> usedSamples = new ArrayList<MetricFamilySamples.Sample>();
112    ArrayList<MetricFamilySamples.Sample> committedSamples = new ArrayList<MetricFamilySamples.Sample>();
113    ArrayList<MetricFamilySamples.Sample> maxSamples = new ArrayList<MetricFamilySamples.Sample>();
114    for (final MemoryPoolMXBean pool : poolBeans) {
115      MemoryUsage poolUsage = pool.getUsage();
116      usedSamples.add(
117          new MetricFamilySamples.Sample(
118              "jvm_memory_pool_bytes_used",
119              Arrays.asList("pool"),
120              Arrays.asList(pool.getName()),
121              poolUsage.getUsed()));
122      committedSamples.add(
123          new MetricFamilySamples.Sample(
124              "jvm_memory_pool_bytes_committed",
125              Arrays.asList("pool"),
126              Arrays.asList(pool.getName()),
127              poolUsage.getCommitted()));
128      maxSamples.add(
129          new MetricFamilySamples.Sample(
130              "jvm_memory_pool_bytes_max",
131              Arrays.asList("pool"),
132              Arrays.asList(pool.getName()),
133              poolUsage.getMax()));
134    }
135    sampleFamilies.add(
136        new MetricFamilySamples(
137            "jvm_memory_pool_bytes_used",
138            Type.GAUGE,
139            "Used bytes of a given JVM memory pool.",
140            usedSamples));
141
142    sampleFamilies.add(
143        new MetricFamilySamples(
144            "jvm_memory_pool_bytes_committed",
145            Type.GAUGE,
146            "Limit (bytes) of a given JVM memory pool.",
147            committedSamples));
148
149    sampleFamilies.add(
150        new MetricFamilySamples(
151            "jvm_memory_pool_bytes_max",
152            Type.GAUGE,
153            "Max (bytes) of a given JVM memory pool.",
154            maxSamples));
155  }
156
157
158  public List<MetricFamilySamples> collect() {
159    List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>();
160    addMemoryAreaMetrics(mfs);
161    addMemoryPoolMetrics(mfs);
162    return mfs;
163  }
164}