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