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