001package io.prometheus.metrics.model.snapshots;
002
003/**
004 * Common base class for histogram and summary data.
005 * Histograms and Summaries represent distributions, like a latency distribution or a distribution
006 * of request sizes in Bytes.
007 */
008public abstract class DistributionDataPointSnapshot extends DataPointSnapshot {
009    private final long count; // optional, negative value means no count.
010    private final double sum; // optional, Double.NaN means no sum.
011    private final Exemplars exemplars; // optional, Exemplars.EMPTY means no Exemplars.
012
013    /**
014     * See JavaDoc of the child classes.
015     */
016    protected DistributionDataPointSnapshot(long count, double sum, Exemplars exemplars, Labels labels, long createdTimestampMillis, long scrapeTimestampMillis) {
017        super(labels, createdTimestampMillis, scrapeTimestampMillis);
018        this.count = count;
019        this.sum = sum;
020        this.exemplars = exemplars == null ? Exemplars.EMPTY : exemplars;
021        validate();
022    }
023
024    private void validate() {
025        // If a histogram or summary observes negative values the sum could be negative.
026        // According to OpenMetrics sum should be omitted in that case, but we don't enforce this here.
027    }
028
029    public boolean hasCount() {
030        return count >= 0;
031    }
032
033    public boolean hasSum() {
034        return !Double.isNaN(sum);
035    }
036
037    /**
038     * This will return garbage if {@link #hasCount()} is {@code false}.
039     */
040    public long getCount() {
041        return count;
042    }
043
044    /**
045     * This will return garbage if {@link #hasSum()} is {@code false}.
046     */
047    public double getSum() {
048        return sum;
049    }
050
051    /**
052     * May be {@link Exemplars#EMPTY}, but will never be {@code null}.
053     */
054    public Exemplars getExemplars() {
055        return exemplars;
056    }
057
058    static abstract class Builder<T extends Builder<T>> extends DataPointSnapshot.Builder<T> {
059
060        protected long count = -1;
061        protected double sum = Double.NaN;
062        protected long createdTimestampMillis = 0L;
063        protected Exemplars exemplars = Exemplars.EMPTY;
064
065        /**
066         * Count can be explicitly set on summaries (this is a public method for summary metrics),
067         * and it is set implicitly on histograms (derived from the bucket counts).
068         */
069        protected T count(long count) {
070            this.count = count;
071            return self();
072        }
073
074        public T sum(double sum) {
075            this.sum = sum;
076            return self();
077        }
078
079        public T exemplars(Exemplars exemplars) {
080            this.exemplars = exemplars;
081            return self();
082        }
083
084        public T createdTimestampMillis(long createdTimestampMillis) {
085            this.createdTimestampMillis = createdTimestampMillis;
086            return self();
087        }
088    }
089}