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