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