001package io.prometheus.metrics.model.snapshots;
002
003import io.prometheus.metrics.annotations.StableApi;
004import io.prometheus.metrics.config.EscapingScheme;
005import java.util.ArrayList;
006import java.util.Collection;
007import java.util.List;
008import javax.annotation.Nullable;
009
010/** Immutable snapshot of an Unknown (Untyped) metric. */
011@StableApi
012public final class UnknownSnapshot extends MetricSnapshot {
013
014  /**
015   * To create a new {@link UnknownSnapshot}, you can either call the constructor directly or use
016   * the builder with {@link UnknownSnapshot#builder()}.
017   *
018   * @param metadata required name and optional help and unit. See {@link MetricMetadata} for naming
019   *     conventions.
020   * @param data the constructor will create a sorted copy of the collection.
021   */
022  public UnknownSnapshot(MetricMetadata metadata, Collection<UnknownDataPointSnapshot> data) {
023    this(metadata, data, false);
024  }
025
026  private UnknownSnapshot(
027      MetricMetadata metadata, Collection<UnknownDataPointSnapshot> data, boolean internal) {
028    super(metadata, data, internal);
029  }
030
031  @SuppressWarnings("unchecked")
032  @Override
033  public List<UnknownDataPointSnapshot> getDataPoints() {
034    return (List<UnknownDataPointSnapshot>) dataPoints;
035  }
036
037  @SuppressWarnings("unchecked")
038  @Override
039  MetricSnapshot escape(
040      EscapingScheme escapingScheme, List<? extends DataPointSnapshot> dataPointSnapshots) {
041    return new UnknownSnapshot(
042        getMetadata().escape(escapingScheme),
043        (List<UnknownDataPointSnapshot>) dataPointSnapshots,
044        true);
045  }
046
047  public static final class UnknownDataPointSnapshot extends DataPointSnapshot {
048
049    private final double value;
050    @Nullable private final Exemplar exemplar;
051
052    /**
053     * To create a new {@link UnknownDataPointSnapshot}, you can either call the constructor
054     * directly or use the Builder with {@link UnknownDataPointSnapshot#builder()}.
055     *
056     * @param value the value.
057     * @param labels must not be null. Use {@link Labels#EMPTY} if there are no labels.
058     * @param exemplar may be null.
059     */
060    public UnknownDataPointSnapshot(double value, Labels labels, @Nullable Exemplar exemplar) {
061      this(value, labels, exemplar, 0);
062    }
063
064    /**
065     * Constructor with an additional scrape timestamp. This is only useful in rare cases as the
066     * scrape timestamp is usually set by the Prometheus server during scraping. Exceptions include
067     * mirroring metrics with given timestamps from other metric sources.
068     */
069    public UnknownDataPointSnapshot(
070        double value, Labels labels, @Nullable Exemplar exemplar, long scrapeTimestampMillis) {
071      this(value, labels, exemplar, scrapeTimestampMillis, false);
072    }
073
074    private UnknownDataPointSnapshot(
075        double value,
076        Labels labels,
077        @Nullable Exemplar exemplar,
078        long scrapeTimestampMillis,
079        boolean internal) {
080      super(labels, 0L, scrapeTimestampMillis, internal);
081      this.value = value;
082      this.exemplar = exemplar;
083    }
084
085    public double getValue() {
086      return value;
087    }
088
089    @Nullable
090    public Exemplar getExemplar() {
091      return exemplar;
092    }
093
094    public static Builder builder() {
095      return new Builder();
096    }
097
098    @Override
099    DataPointSnapshot escape(EscapingScheme escapingScheme) {
100      return new UnknownDataPointSnapshot(
101          value,
102          SnapshotEscaper.escapeLabels(getLabels(), escapingScheme),
103          SnapshotEscaper.escapeExemplar(exemplar, escapingScheme),
104          getScrapeTimestampMillis(),
105          true);
106    }
107
108    public static class Builder extends DataPointSnapshot.Builder<Builder> {
109
110      @Nullable private Exemplar exemplar = null;
111      @Nullable private Double value = null;
112
113      private Builder() {}
114
115      /** required. */
116      public Builder value(double value) {
117        this.value = value;
118        return this;
119      }
120
121      /** Optional */
122      public Builder exemplar(@Nullable Exemplar exemplar) {
123        this.exemplar = exemplar;
124        return this;
125      }
126
127      public UnknownDataPointSnapshot build() {
128        if (value == null) {
129          throw new IllegalArgumentException("Missing required field: value is null.");
130        }
131        return new UnknownDataPointSnapshot(value, labels, exemplar, scrapeTimestampMillis);
132      }
133
134      @Override
135      protected Builder self() {
136        return this;
137      }
138    }
139  }
140
141  public static Builder builder() {
142    return new Builder();
143  }
144
145  public static class Builder extends MetricSnapshot.Builder<Builder> {
146
147    private final List<UnknownDataPointSnapshot> dataPoints = new ArrayList<>();
148
149    private Builder() {}
150
151    /** Add a data point. Call multiple times to add multiple data points. */
152    public Builder dataPoint(UnknownDataPointSnapshot data) {
153      dataPoints.add(data);
154      return this;
155    }
156
157    @Override
158    public UnknownSnapshot build() {
159      return new UnknownSnapshot(buildMetadata(), dataPoints);
160    }
161
162    @Override
163    protected Builder self() {
164      return this;
165    }
166  }
167}