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