001package io.prometheus.metrics.instrumentation.jvm;
002
003import io.prometheus.metrics.config.PrometheusProperties;
004import io.prometheus.metrics.core.metrics.CounterWithCallback;
005import io.prometheus.metrics.model.registry.PrometheusRegistry;
006import io.prometheus.metrics.model.snapshots.Unit;
007
008import java.lang.management.CompilationMXBean;
009import java.lang.management.ManagementFactory;
010
011import static io.prometheus.metrics.model.snapshots.Unit.millisToSeconds;
012
013/**
014 * JVM Compilation metrics. The {@link JvmCompilationMetrics} 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 JvmCompilationMetrics} you can also register them directly:
019 * <pre>{@code
020 *   JvmCompilationMetrics.builder().register();
021 * }</pre>
022 * Example metrics being exported:
023 * <pre>
024 * # HELP jvm_compilation_time_seconds_total The total time in seconds taken for HotSpot class compilation
025 * # TYPE jvm_compilation_time_seconds_total counter
026 * jvm_compilation_time_seconds_total 0.152
027 * </pre>
028 */
029public class JvmCompilationMetrics {
030
031    private static final String JVM_COMPILATION_TIME_SECONDS_TOTAL = "jvm_compilation_time_seconds_total";
032
033    private final PrometheusProperties config;
034    private final CompilationMXBean compilationBean;
035
036    private JvmCompilationMetrics(CompilationMXBean compilationBean, PrometheusProperties config) {
037        this.compilationBean = compilationBean;
038        this.config = config;
039    }
040
041    private void register(PrometheusRegistry registry) {
042
043        if (compilationBean == null || !compilationBean.isCompilationTimeMonitoringSupported()) {
044            return;
045        }
046
047        CounterWithCallback.builder(config)
048                .name(JVM_COMPILATION_TIME_SECONDS_TOTAL)
049                .help("The total time in seconds taken for HotSpot class compilation")
050                .unit(Unit.SECONDS)
051                .callback(callback -> callback.call(millisToSeconds(compilationBean.getTotalCompilationTime())))
052                .register(registry);
053    }
054
055    public static Builder builder() {
056        return new Builder(PrometheusProperties.get());
057    }
058
059    public static Builder builder(PrometheusProperties config) {
060        return new Builder(config);
061    }
062
063    public static class Builder {
064
065        private final PrometheusProperties config;
066        private CompilationMXBean compilationBean;
067
068        private Builder(PrometheusProperties config) {
069            this.config = config;
070        }
071
072        /**
073         * Package private. For testing only.
074         */
075        Builder compilationBean(CompilationMXBean compilationBean) {
076            this.compilationBean = compilationBean;
077            return this;
078        }
079
080        public void register() {
081            register(PrometheusRegistry.defaultRegistry);
082        }
083
084        public void register(PrometheusRegistry registry) {
085            CompilationMXBean compilationBean = this.compilationBean != null ? this.compilationBean : ManagementFactory.getCompilationMXBean();
086            new JvmCompilationMetrics(compilationBean, config).register(registry);
087        }
088    }
089}