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