001package io.prometheus.metrics.model.snapshots;
002
003import io.prometheus.metrics.annotations.StableApi;
004import java.util.ArrayList;
005import java.util.Arrays;
006import java.util.Collections;
007import java.util.Comparator;
008import java.util.Iterator;
009import java.util.List;
010
011/** Immutable list of quantiles. */
012@StableApi
013public class Quantiles implements Iterable<Quantile> {
014
015  private final List<Quantile> quantiles;
016  public static final Quantiles EMPTY = new Quantiles(Collections.emptyList());
017
018  private Quantiles(List<Quantile> quantiles) {
019    quantiles = new ArrayList<>(quantiles);
020    quantiles.sort(Comparator.comparing(Quantile::getQuantile));
021    this.quantiles = Collections.unmodifiableList(quantiles);
022    validate();
023  }
024
025  private void validate() {
026    for (int i = 0; i < quantiles.size() - 1; i++) {
027      if (quantiles.get(i).getQuantile() == quantiles.get(i + 1).getQuantile()) {
028        throw new IllegalArgumentException(
029            "Duplicate " + quantiles.get(i).getQuantile() + " quantile.");
030      }
031    }
032  }
033
034  /**
035   * Create a new Quantiles instance. You can either create Quantiles with one of the static {@code
036   * Quantiles.of(...)} methods, or you can use the {@link Quantiles#builder()}.
037   */
038  public static Quantiles of(List<Quantile> quantiles) {
039    return new Quantiles(quantiles);
040  }
041
042  /**
043   * Create a new Quantiles instance. You can either create Quantiles with one of the static {@code
044   * Quantiles.of(...)} methods, or you can use the {@link Quantiles#builder()}.
045   */
046  public static Quantiles of(Quantile... quantiles) {
047    return of(Arrays.asList(quantiles));
048  }
049
050  public int size() {
051    return quantiles.size();
052  }
053
054  public Quantile get(int i) {
055    return quantiles.get(i);
056  }
057
058  @Override
059  public Iterator<Quantile> iterator() {
060    return quantiles.iterator();
061  }
062
063  public static Builder builder() {
064    return new Builder();
065  }
066
067  public static class Builder {
068
069    private final List<Quantile> quantiles = new ArrayList<>();
070
071    private Builder() {}
072
073    /** Add a quantile. Call multiple times to add multiple quantiles. */
074    public Builder quantile(Quantile quantile) {
075      quantiles.add(quantile);
076      return this;
077    }
078
079    /**
080     * Add a quantile. Call multiple times to add multiple quantiles.
081     *
082     * @param quantile 0.0 &lt;= quantile &lt;= 1.0
083     * @param value the quantile value
084     */
085    public Builder quantile(double quantile, double value) {
086      quantiles.add(new Quantile(quantile, value));
087      return this;
088    }
089
090    public Quantiles build() {
091      return new Quantiles(quantiles);
092    }
093  }
094}