001package io.prometheus.client.hotspot;
002
003import io.prometheus.client.Collector;
004import io.prometheus.client.CounterMetricFamily;
005import io.prometheus.client.GaugeMetricFamily;
006import io.prometheus.client.Predicate;
007
008import java.lang.management.ManagementFactory;
009import java.lang.management.ClassLoadingMXBean;
010import java.util.ArrayList;
011import java.util.List;
012
013import static io.prometheus.client.SampleNameFilter.ALLOW_ALL;
014
015/**
016 * Exports metrics about JVM classloading.
017 * <p>
018 * Example usage:
019 * <pre>
020 * {@code
021 *   new ClassLoadingExports().register();
022 * }
023 * </pre>
024 * Example metrics being exported:
025 * <pre>
026 *   jvm_classes_currently_loaded{} 1000
027 *   jvm_classes_loaded_total{} 2000
028 *   jvm_classes_unloaded_total{} 500
029 * </pre>
030 */
031public class ClassLoadingExports extends Collector {
032
033  private static final String JVM_CLASSES_CURRENTLY_LOADED = "jvm_classes_currently_loaded";
034  private static final String JVM_CLASSES_LOADED_TOTAL = "jvm_classes_loaded_total";
035  private static final String JVM_CLASSES_UNLOADED_TOTAL = "jvm_classes_unloaded_total";
036
037  private final ClassLoadingMXBean clBean;
038
039  public ClassLoadingExports() {
040    this(ManagementFactory.getClassLoadingMXBean());
041  }
042
043  public ClassLoadingExports(ClassLoadingMXBean clBean) {
044    this.clBean = clBean;
045  }
046
047  void addClassLoadingMetrics(List<MetricFamilySamples> sampleFamilies, Predicate<String> nameFilter) {
048    if (nameFilter.test(JVM_CLASSES_CURRENTLY_LOADED)) {
049      sampleFamilies.add(new GaugeMetricFamily(
050              JVM_CLASSES_CURRENTLY_LOADED,
051              "The number of classes that are currently loaded in the JVM",
052              clBean.getLoadedClassCount()));
053    }
054    if (nameFilter.test(JVM_CLASSES_LOADED_TOTAL)) {
055      sampleFamilies.add(new CounterMetricFamily(
056              JVM_CLASSES_LOADED_TOTAL,
057              "The total number of classes that have been loaded since the JVM has started execution",
058              clBean.getTotalLoadedClassCount()));
059    }
060    if (nameFilter.test(JVM_CLASSES_UNLOADED_TOTAL)) {
061      sampleFamilies.add(new CounterMetricFamily(
062              JVM_CLASSES_UNLOADED_TOTAL,
063              "The total number of classes that have been unloaded since the JVM has started execution",
064              clBean.getUnloadedClassCount()));
065    }
066  }
067
068  @Override
069  public List<MetricFamilySamples> collect() {
070    return collect(null);
071  }
072
073  @Override
074  public List<MetricFamilySamples> collect(Predicate<String> nameFilter) {
075    List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>();
076    addClassLoadingMetrics(mfs, nameFilter == null ? ALLOW_ALL : nameFilter);
077    return mfs;
078  }
079}