001package io.prometheus.metrics.model.snapshots;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.List;
006
007/**
008 * Immutable snapshot of a Summary metric.
009 */
010public final class SummarySnapshot extends MetricSnapshot {
011
012    /**
013     * To create a new {@link SummarySnapshot}, you can either call the constructor directly or use
014     * the builder with {@link SummarySnapshot#builder()}.
015     *
016     * @param metadata See {@link MetricMetadata} for more naming conventions.
017     * @param data     the constructor will create a sorted copy of the collection.
018     */
019    public SummarySnapshot(MetricMetadata metadata, Collection<SummaryDataPointSnapshot> data) {
020        super(metadata, data);
021    }
022
023    @Override
024    public List<SummaryDataPointSnapshot> getDataPoints() {
025        return (List<SummaryDataPointSnapshot>) dataPoints;
026    }
027
028    public static final class SummaryDataPointSnapshot extends DistributionDataPointSnapshot {
029
030        private final Quantiles quantiles;
031
032
033        /**
034         * To create a new {@link SummaryDataPointSnapshot}, you can either call the constructor directly
035         * or use the Builder with {@link SummaryDataPointSnapshot#builder()}.
036         *
037         * @param count                  total number of observations. Optional, pass -1 if not available.
038         * @param sum                    sum of all observed values. Optional, pass {@link Double#NaN} if not available.
039         * @param quantiles              must not be {@code null}. Use {@link Quantiles#EMPTY} if there are no quantiles.
040         * @param labels                 must not be {@code null}. Use {@link Labels#EMPTY} if there are no labels.
041         * @param exemplars              must not be {@code null}. Use {@link Exemplars#EMPTY} if there are no exemplars.
042         * @param createdTimestampMillis timestamp (as in {@link System#currentTimeMillis()}) when this summary
043         *                               data (this specific set of labels) was created.
044         *                               Note that this refers to the creation of the timeseries,
045         *                               not the creation of the snapshot.
046         *                               The created timestamp optional. Use {@code 0L} if there is no created timestamp.
047         */
048        public SummaryDataPointSnapshot(long count, double sum, Quantiles quantiles, Labels labels, Exemplars exemplars, long createdTimestampMillis) {
049            this(count, sum, quantiles, labels, exemplars, createdTimestampMillis, 0);
050        }
051
052        /**
053         * Constructor with an additional scrape timestamp.
054         * This is only useful in rare cases as the scrape timestamp is usually set by the Prometheus server
055         * during scraping. Exceptions include mirroring metrics with given timestamps from other metric sources.
056         */
057        public SummaryDataPointSnapshot(long count, double sum, Quantiles quantiles, Labels labels, Exemplars exemplars, long createdTimestampMillis, long scrapeTimestampMillis) {
058            super(count, sum, exemplars, labels, createdTimestampMillis, scrapeTimestampMillis);
059            this.quantiles = quantiles;
060            validate();
061        }
062
063        public Quantiles getQuantiles() {
064            return quantiles;
065        }
066
067        private void validate() {
068            for (Label label : getLabels()) {
069                if (label.getName().equals("quantile")) {
070                    throw new IllegalArgumentException("quantile is a reserved label name for summaries");
071                }
072            }
073            if (quantiles == null) {
074                throw new NullPointerException();
075            }
076        }
077
078        public static Builder builder() {
079            return new Builder();
080        }
081
082        public static class Builder extends DistributionDataPointSnapshot.Builder<Builder> {
083
084            private Quantiles quantiles = Quantiles.EMPTY;
085
086            private Builder() {
087            }
088
089            @Override
090            protected Builder self() {
091                return this;
092            }
093
094            public Builder quantiles(Quantiles quantiles) {
095                this.quantiles = quantiles;
096                return this;
097            }
098
099            @Override
100            public Builder count(long count) {
101                super.count(count);
102                return this;
103            }
104
105            public SummaryDataPointSnapshot build() {
106                return new SummaryDataPointSnapshot(count, sum, quantiles, labels, exemplars, createdTimestampMillis, scrapeTimestampMillis);
107            }
108        }
109    }
110
111    public static Builder builder() {
112        return new Builder();
113    }
114
115    public static class Builder extends MetricSnapshot.Builder<Builder> {
116
117        private final List<SummaryDataPointSnapshot> dataPoints = new ArrayList<>();
118
119        private Builder() {
120        }
121
122        /**
123         * Add a data point. Call multiple times to add multiple data points.
124         */
125        public Builder dataPoint(SummaryDataPointSnapshot data) {
126            dataPoints.add(data);
127            return this;
128        }
129
130        @Override
131        public SummarySnapshot build() {
132            return new SummarySnapshot(buildMetadata(), dataPoints);
133        }
134
135        @Override
136        protected Builder self() {
137            return this;
138        }
139    }
140}