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 Info metric. */
011@StableApi
012public final class InfoSnapshot extends MetricSnapshot {
013
014  /**
015   * To create a new {@link InfoSnapshot}, you can either call the constructor directly or use the
016   * builder with {@link InfoSnapshot#builder()}.
017   *
018   * @param metadata the metric name in metadata must not include the {@code _info} suffix. See
019   *     {@link MetricMetadata} for more naming conventions. The metadata must not have a unit.
020   * @param data the constructor will create a sorted copy of the collection.
021   */
022  public InfoSnapshot(MetricMetadata metadata, Collection<InfoDataPointSnapshot> data) {
023    this(metadata, data, false);
024    if (metadata.hasUnit()) {
025      throw new IllegalArgumentException("An Info metric cannot have a unit.");
026    }
027  }
028
029  private InfoSnapshot(
030      MetricMetadata metadata, Collection<InfoDataPointSnapshot> data, boolean internal) {
031    super(metadata, data, internal);
032  }
033
034  @SuppressWarnings("unchecked")
035  @Override
036  public List<InfoDataPointSnapshot> getDataPoints() {
037    return (List<InfoDataPointSnapshot>) dataPoints;
038  }
039
040  @SuppressWarnings("unchecked")
041  @Override
042  MetricSnapshot escape(
043      EscapingScheme escapingScheme, List<? extends DataPointSnapshot> dataPointSnapshots) {
044    return new InfoSnapshot(
045        getMetadata().escape(escapingScheme),
046        (List<InfoSnapshot.InfoDataPointSnapshot>) dataPointSnapshots,
047        true);
048  }
049
050  public static class InfoDataPointSnapshot extends DataPointSnapshot {
051
052    /**
053     * To create a new {@link InfoDataPointSnapshot}, you can either call the constructor directly
054     * or use the Builder with {@link InfoDataPointSnapshot#builder()}.
055     *
056     * @param labels must not be null. Use {@link Labels#EMPTY} if there are no labels.
057     */
058    public InfoDataPointSnapshot(Labels labels) {
059      this(labels, 0L);
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 InfoDataPointSnapshot(Labels labels, long scrapeTimestampMillis) {
068      this(labels, scrapeTimestampMillis, false);
069    }
070
071    private InfoDataPointSnapshot(Labels labels, long scrapeTimestampMillis, boolean internal) {
072      super(labels, 0L, scrapeTimestampMillis, internal);
073    }
074
075    public static Builder builder() {
076      return new Builder();
077    }
078
079    @Override
080    DataPointSnapshot escape(EscapingScheme escapingScheme) {
081      return new InfoSnapshot.InfoDataPointSnapshot(
082          SnapshotEscaper.escapeLabels(getLabels(), escapingScheme),
083          getScrapeTimestampMillis(),
084          true);
085    }
086
087    public static class Builder extends DataPointSnapshot.Builder<Builder> {
088
089      private Builder() {}
090
091      public InfoDataPointSnapshot build() {
092        return new InfoDataPointSnapshot(labels, scrapeTimestampMillis, true);
093      }
094
095      @Override
096      protected Builder self() {
097        return this;
098      }
099    }
100  }
101
102  public static Builder builder() {
103    return new Builder();
104  }
105
106  public static class Builder extends MetricSnapshot.Builder<Builder> {
107
108    private final List<InfoDataPointSnapshot> dataPoints = new ArrayList<>();
109
110    private Builder() {}
111
112    /** Add a data point. Call multiple times for adding multiple data points. */
113    public Builder dataPoint(InfoDataPointSnapshot dataPoint) {
114      dataPoints.add(dataPoint);
115      return this;
116    }
117
118    @Override
119    public Builder unit(@Nullable Unit unit) {
120      throw new IllegalArgumentException("Info metric cannot have a unit.");
121    }
122
123    @Override
124    protected MetricMetadata buildMetadata() {
125      if (name == null) {
126        throw new IllegalArgumentException("Missing required field: name is null");
127      }
128      return MetricMetadataSupport.infoMetadata(name, help);
129    }
130
131    @Override
132    public InfoSnapshot build() {
133      return new InfoSnapshot(buildMetadata(), dataPoints);
134    }
135
136    @Override
137    protected Builder self() {
138      return this;
139    }
140  }
141}