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.Exemplars; 006import io.prometheus.metrics.model.snapshots.Quantiles; 007import io.prometheus.metrics.model.snapshots.SummarySnapshot; 008import java.util.ArrayList; 009import java.util.Collections; 010import java.util.List; 011import java.util.function.Consumer; 012import javax.annotation.Nullable; 013 014/** 015 * Example: 016 * 017 * <pre>{@code 018 * double MILLISECONDS_PER_SECOND = 1E3; 019 * 020 * SummaryWithCallback.builder() 021 * .name("jvm_gc_collection_seconds") 022 * .help("Time spent in a given JVM garbage collector in seconds.") 023 * .unit(Unit.SECONDS) 024 * .labelNames("gc") 025 * .callback(callback -> { 026 * for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) { 027 * callback.call( 028 * gc.getCollectionCount(), 029 * gc.getCollectionTime() / MILLISECONDS_PER_SECOND, 030 * Quantiles.EMPTY, 031 * gc.getName() 032 * ); 033 * } 034 * }) 035 * .register(); 036 * }</pre> 037 */ 038public class SummaryWithCallback extends CallbackMetric { 039 040 @FunctionalInterface 041 public interface Callback { 042 void call(long count, double sum, Quantiles quantiles, String... labelValues); 043 } 044 045 private final Consumer<Callback> callback; 046 047 private SummaryWithCallback(Builder builder) { 048 super(builder); 049 if (builder.callback == null) { 050 throw new IllegalArgumentException("callback cannot be null"); 051 } 052 this.callback = builder.callback; 053 } 054 055 @Override 056 public SummarySnapshot collect() { 057 List<SummarySnapshot.SummaryDataPointSnapshot> dataPoints = new ArrayList<>(); 058 callback.accept( 059 (count, sum, quantiles, labelValues) -> { 060 dataPoints.add( 061 new SummarySnapshot.SummaryDataPointSnapshot( 062 count, sum, quantiles, makeLabels(labelValues), Exemplars.EMPTY, 0L)); 063 }); 064 return new SummarySnapshot(getMetadata(), dataPoints); 065 } 066 067 @Override 068 public MetricType getMetricType() { 069 return MetricType.SUMMARY; 070 } 071 072 public static Builder builder() { 073 return new Builder(PrometheusProperties.get()); 074 } 075 076 public static Builder builder(PrometheusProperties properties) { 077 return new Builder(properties); 078 } 079 080 public static class Builder 081 extends CallbackMetric.Builder<SummaryWithCallback.Builder, SummaryWithCallback> { 082 083 @Nullable private Consumer<Callback> callback; 084 085 public Builder callback(Consumer<Callback> callback) { 086 this.callback = callback; 087 return self(); 088 } 089 090 private Builder(PrometheusProperties properties) { 091 super(Collections.singletonList("quantile"), properties); 092 } 093 094 @Override 095 public SummaryWithCallback build() { 096 return new SummaryWithCallback(this); 097 } 098 099 @Override 100 protected Builder self() { 101 return this; 102 } 103 } 104}