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      boolean internal) {
021    super(labels, createdTimestampMillis, scrapeTimestampMillis, internal);
022    this.count = count;
023    this.sum = sum;
024    this.exemplars = exemplars == null ? Exemplars.EMPTY : exemplars;
025    if (!internal) {
026      validate();
027    }
028  }
029
030  private void validate() {
031    // If a histogram or summary observes negative values the sum could be negative.
032    // According to OpenMetrics sum should be omitted in that case, but we don't enforce this here.
033  }
034
035  public boolean hasCount() {
036    return count >= 0;
037  }
038
039  public boolean hasSum() {
040    return !Double.isNaN(sum);
041  }
042
043  /** This will return garbage if {@link #hasCount()} is {@code false}. */
044  public long getCount() {
045    return count;
046  }
047
048  /** This will return garbage if {@link #hasSum()} is {@code false}. */
049  public double getSum() {
050    return sum;
051  }
052
053  /** May be {@link Exemplars#EMPTY}, but will never be {@code null}. */
054  public Exemplars getExemplars() {
055    return exemplars;
056  }
057
058  abstract static 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), and
067     * 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}