001package io.prometheus.metrics.instrumentation.jvm; 002 003import io.prometheus.metrics.config.PrometheusProperties; 004import io.prometheus.metrics.core.metrics.SummaryWithCallback; 005import io.prometheus.metrics.model.registry.PrometheusRegistry; 006import io.prometheus.metrics.model.snapshots.Quantiles; 007import io.prometheus.metrics.model.snapshots.Unit; 008import java.lang.management.GarbageCollectorMXBean; 009import java.lang.management.ManagementFactory; 010import java.util.List; 011import javax.annotation.Nullable; 012 013/** 014 * JVM Garbage Collector metrics. The {@link JvmGarbageCollectorMetrics} are registered as part of 015 * the {@link JvmMetrics} like this: 016 * 017 * <pre>{@code 018 * JvmMetrics.builder().register(); 019 * }</pre> 020 * 021 * However, if you want only the {@link JvmGarbageCollectorMetrics} you can also register them 022 * directly: 023 * 024 * <pre>{@code 025 * JvmGarbageCollectorMetrics.builder().register(); 026 * }</pre> 027 * 028 * Example metrics being exported: 029 * 030 * <pre> 031 * # HELP jvm_gc_collection_seconds Time spent in a given JVM garbage collector in seconds. 032 * # TYPE jvm_gc_collection_seconds summary 033 * jvm_gc_collection_seconds_count{gc="PS MarkSweep"} 0 034 * jvm_gc_collection_seconds_sum{gc="PS MarkSweep"} 0.0 035 * jvm_gc_collection_seconds_count{gc="PS Scavenge"} 0 036 * jvm_gc_collection_seconds_sum{gc="PS Scavenge"} 0.0 037 * </pre> 038 */ 039public class JvmGarbageCollectorMetrics { 040 041 private static final String JVM_GC_COLLECTION_SECONDS = "jvm_gc_collection_seconds"; 042 043 private final PrometheusProperties config; 044 private final List<GarbageCollectorMXBean> garbageCollectorBeans; 045 046 private JvmGarbageCollectorMetrics( 047 List<GarbageCollectorMXBean> garbageCollectorBeans, PrometheusProperties config) { 048 this.config = config; 049 this.garbageCollectorBeans = garbageCollectorBeans; 050 } 051 052 private void register(PrometheusRegistry registry) { 053 054 SummaryWithCallback.builder(config) 055 .name(JVM_GC_COLLECTION_SECONDS) 056 .help("Time spent in a given JVM garbage collector in seconds.") 057 .unit(Unit.SECONDS) 058 .labelNames("gc") 059 .callback( 060 callback -> { 061 for (GarbageCollectorMXBean gc : garbageCollectorBeans) { 062 callback.call( 063 gc.getCollectionCount(), 064 Unit.millisToSeconds(gc.getCollectionTime()), 065 Quantiles.EMPTY, 066 gc.getName()); 067 } 068 }) 069 .register(registry); 070 } 071 072 public static Builder builder() { 073 return new Builder(PrometheusProperties.get()); 074 } 075 076 public static Builder builder(PrometheusProperties config) { 077 return new Builder(config); 078 } 079 080 public static class Builder { 081 082 private final PrometheusProperties config; 083 @Nullable private List<GarbageCollectorMXBean> garbageCollectorBeans; 084 085 private Builder(PrometheusProperties config) { 086 this.config = config; 087 } 088 089 /** Package private. For testing only. */ 090 Builder garbageCollectorBeans(List<GarbageCollectorMXBean> garbageCollectorBeans) { 091 this.garbageCollectorBeans = garbageCollectorBeans; 092 return this; 093 } 094 095 public void register() { 096 register(PrometheusRegistry.defaultRegistry); 097 } 098 099 public void register(PrometheusRegistry registry) { 100 List<GarbageCollectorMXBean> garbageCollectorBeans = this.garbageCollectorBeans; 101 if (garbageCollectorBeans == null) { 102 garbageCollectorBeans = ManagementFactory.getGarbageCollectorMXBeans(); 103 } 104 new JvmGarbageCollectorMetrics(garbageCollectorBeans, config).register(registry); 105 } 106 } 107}