001package io.prometheus.metrics.instrumentation.jvm; 002 003import io.prometheus.metrics.config.PrometheusProperties; 004import io.prometheus.metrics.core.metrics.CounterWithCallback; 005import io.prometheus.metrics.core.metrics.GaugeWithCallback; 006import io.prometheus.metrics.model.registry.PrometheusRegistry; 007import java.lang.management.ClassLoadingMXBean; 008import java.lang.management.ManagementFactory; 009import javax.annotation.Nullable; 010 011/** 012 * JVM Class Loading metrics. The {@link JvmClassLoadingMetrics} are registered as part of the 013 * {@link JvmMetrics} like this: 014 * 015 * <pre>{@code 016 * JvmMetrics.builder().register(); 017 * }</pre> 018 * 019 * However, if you want only the {@link JvmClassLoadingMetrics} you can also register them directly: 020 * 021 * <pre>{@code 022 * JvmClassLoadingMetrics.builder().register(); 023 * }</pre> 024 * 025 * Example metrics being exported: 026 * 027 * <pre> 028 * # HELP jvm_classes_currently_loaded The number of classes that are currently loaded in the JVM 029 * # TYPE jvm_classes_currently_loaded gauge 030 * jvm_classes_currently_loaded 1109.0 031 * # HELP jvm_classes_loaded_total The total number of classes that have been loaded since the JVM has started execution 032 * # TYPE jvm_classes_loaded_total counter 033 * jvm_classes_loaded_total 1109.0 034 * # HELP jvm_classes_unloaded_total The total number of classes that have been unloaded since the JVM has started execution 035 * # TYPE jvm_classes_unloaded_total counter 036 * jvm_classes_unloaded_total 0.0 037 * </pre> 038 */ 039public class JvmClassLoadingMetrics { 040 041 private static final String JVM_CLASSES_CURRENTLY_LOADED = "jvm_classes_currently_loaded"; 042 private static final String JVM_CLASSES_LOADED_TOTAL = "jvm_classes_loaded_total"; 043 private static final String JVM_CLASSES_UNLOADED_TOTAL = "jvm_classes_unloaded_total"; 044 045 private final PrometheusProperties config; 046 private final ClassLoadingMXBean classLoadingBean; 047 048 private JvmClassLoadingMetrics(ClassLoadingMXBean classLoadingBean, PrometheusProperties config) { 049 this.classLoadingBean = classLoadingBean; 050 this.config = config; 051 } 052 053 private void register(PrometheusRegistry registry) { 054 055 GaugeWithCallback.builder(config) 056 .name(JVM_CLASSES_CURRENTLY_LOADED) 057 .help("The number of classes that are currently loaded in the JVM") 058 .callback(callback -> callback.call(classLoadingBean.getLoadedClassCount())) 059 .register(registry); 060 061 CounterWithCallback.builder(config) 062 .name(JVM_CLASSES_LOADED_TOTAL) 063 .help( 064 "The total number of classes that have been loaded since the JVM has started execution") 065 .callback(callback -> callback.call(classLoadingBean.getTotalLoadedClassCount())) 066 .register(registry); 067 068 CounterWithCallback.builder(config) 069 .name(JVM_CLASSES_UNLOADED_TOTAL) 070 .help( 071 "The total number of classes that have been unloaded since the JVM has " 072 + "started execution") 073 .callback(callback -> callback.call(classLoadingBean.getUnloadedClassCount())) 074 .register(registry); 075 } 076 077 public static Builder builder() { 078 return new Builder(PrometheusProperties.get()); 079 } 080 081 public static Builder builder(PrometheusProperties config) { 082 return new Builder(config); 083 } 084 085 public static class Builder { 086 087 private final PrometheusProperties config; 088 @Nullable private ClassLoadingMXBean classLoadingBean; 089 090 private Builder(PrometheusProperties config) { 091 this.config = config; 092 } 093 094 /** Package private. For testing only. */ 095 Builder classLoadingBean(ClassLoadingMXBean classLoadingBean) { 096 this.classLoadingBean = classLoadingBean; 097 return this; 098 } 099 100 public void register() { 101 register(PrometheusRegistry.defaultRegistry); 102 } 103 104 public void register(PrometheusRegistry registry) { 105 ClassLoadingMXBean classLoadingBean = 106 this.classLoadingBean != null 107 ? this.classLoadingBean 108 : ManagementFactory.getClassLoadingMXBean(); 109 new JvmClassLoadingMetrics(classLoadingBean, config).register(registry); 110 } 111 } 112}