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