001package io.prometheus.metrics.core.metrics;
002
003import io.prometheus.metrics.config.PrometheusProperties;
004import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
005
006import java.util.ArrayList;
007import java.util.Collections;
008import java.util.List;
009import java.util.function.Consumer;
010
011/**
012 * Example:
013 * <pre>{@code
014 * MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
015 *
016 * GaugeWithCallback.builder()
017 *     .name("jvm_memory_bytes_used")
018 *     .help("Used bytes of a given JVM memory area.")
019 *     .unit(Unit.BYTES)
020 *     .labelNames("area")
021 *     .callback(callback -> {
022 *         callback.call(memoryBean.getHeapMemoryUsage().getUsed(), "heap");
023 *         callback.call(memoryBean.getNonHeapMemoryUsage().getUsed(), "nonheap");
024 *     })
025 *     .register();
026 * }</pre>
027 */
028public class GaugeWithCallback extends CallbackMetric {
029
030    @FunctionalInterface
031    public interface Callback {
032        void call(double value, String... labelValues);
033    }
034
035    private final Consumer<Callback> callback;
036
037    private GaugeWithCallback(Builder builder) {
038        super(builder);
039        this.callback = builder.callback;
040        if (callback == null) {
041            throw new IllegalArgumentException("callback cannot be null");
042        }
043    }
044
045    @Override
046    public GaugeSnapshot collect() {
047        List<GaugeSnapshot.GaugeDataPointSnapshot> dataPoints = new ArrayList<>();
048        callback.accept((value, labelValues) -> {
049            dataPoints.add(new GaugeSnapshot.GaugeDataPointSnapshot(value, makeLabels(labelValues), null, 0L));
050        });
051        return new GaugeSnapshot(getMetadata(), dataPoints);
052    }
053
054    public static Builder builder() {
055        return new Builder(PrometheusProperties.get());
056    }
057
058    public static Builder builder(PrometheusProperties properties) {
059        return new Builder(properties);
060    }
061
062    public static class Builder extends CallbackMetric.Builder<GaugeWithCallback.Builder, GaugeWithCallback> {
063
064        private Consumer<Callback> callback;
065
066        public Builder callback(Consumer<Callback> callback) {
067            this.callback = callback;
068            return self();
069        }
070
071        private Builder(PrometheusProperties properties) {
072            super(Collections.emptyList(), properties);
073        }
074
075        @Override
076        public GaugeWithCallback build() {
077            return new GaugeWithCallback(this);
078        }
079
080        @Override
081        protected Builder self() {
082            return this;
083        }
084    }
085}