001package io.prometheus.metrics.config;
002
003import java.util.Map;
004import javax.annotation.Nullable;
005
006/** Properties starting with io.prometheus.exemplars */
007public class ExemplarsProperties {
008
009  private static final String PREFIX = "io.prometheus.exemplars";
010  private static final String MIN_RETENTION_PERIOD_SECONDS = "minRetentionPeriodSeconds";
011  private static final String MAX_RETENTION_PERIOD_SECONDS = "maxRetentionPeriodSeconds";
012  private static final String SAMPLE_INTERVAL_MILLISECONDS = "sampleIntervalMilliseconds";
013
014  @Nullable private final Integer minRetentionPeriodSeconds;
015  @Nullable private final Integer maxRetentionPeriodSeconds;
016  @Nullable private final Integer sampleIntervalMilliseconds;
017
018  private ExemplarsProperties(
019      @Nullable Integer minRetentionPeriodSeconds,
020      @Nullable Integer maxRetentionPeriodSeconds,
021      @Nullable Integer sampleIntervalMilliseconds) {
022    this.minRetentionPeriodSeconds = minRetentionPeriodSeconds;
023    this.maxRetentionPeriodSeconds = maxRetentionPeriodSeconds;
024    this.sampleIntervalMilliseconds = sampleIntervalMilliseconds;
025  }
026
027  /**
028   * Minimum time how long Exemplars are kept before they may be replaced by new Exemplars.
029   *
030   * <p>Default see {@code ExemplarSamplerConfig.DEFAULT_MIN_RETENTION_PERIOD_SECONDS}
031   */
032  @Nullable
033  public Integer getMinRetentionPeriodSeconds() {
034    return minRetentionPeriodSeconds;
035  }
036
037  /**
038   * Maximum time how long Exemplars are kept before they are evicted.
039   *
040   * <p>Default see {@code ExemplarSamplerConfig.DEFAULT_MAX_RETENTION_PERIOD_SECONDS}
041   */
042  @Nullable
043  public Integer getMaxRetentionPeriodSeconds() {
044    return maxRetentionPeriodSeconds;
045  }
046
047  /**
048   * Time between attempts to sample new Exemplars. This is a performance improvement for
049   * high-frequency applications, because with the sample interval we make sure that the exemplar
050   * sampler is not called for every single request.
051   *
052   * <p>Default see {@code ExemplarSamplerConfig.DEFAULT_SAMPLE_INTERVAL_MILLISECONDS}
053   */
054  @Nullable
055  public Integer getSampleIntervalMilliseconds() {
056    return sampleIntervalMilliseconds;
057  }
058
059  /**
060   * Note that this will remove entries from {@code properties}. This is because we want to know if
061   * there are unused properties remaining after all properties have been loaded.
062   */
063  static ExemplarsProperties load(Map<Object, Object> properties)
064      throws PrometheusPropertiesException {
065    Integer minRetentionPeriodSeconds =
066        Util.loadInteger(PREFIX + "." + MIN_RETENTION_PERIOD_SECONDS, properties);
067    Integer maxRetentionPeriodSeconds =
068        Util.loadInteger(PREFIX + "." + MAX_RETENTION_PERIOD_SECONDS, properties);
069    Integer sampleIntervalMilliseconds =
070        Util.loadInteger(PREFIX + "." + SAMPLE_INTERVAL_MILLISECONDS, properties);
071
072    Util.assertValue(
073        minRetentionPeriodSeconds,
074        t -> t > 0,
075        "Expecting value > 0.",
076        PREFIX,
077        MIN_RETENTION_PERIOD_SECONDS);
078    Util.assertValue(
079        maxRetentionPeriodSeconds,
080        t -> t > 0,
081        "Expecting value > 0.",
082        PREFIX,
083        MAX_RETENTION_PERIOD_SECONDS);
084    Util.assertValue(
085        sampleIntervalMilliseconds,
086        t -> t > 0,
087        "Expecting value > 0.",
088        PREFIX,
089        SAMPLE_INTERVAL_MILLISECONDS);
090
091    if (minRetentionPeriodSeconds != null && maxRetentionPeriodSeconds != null) {
092      if (minRetentionPeriodSeconds > maxRetentionPeriodSeconds) {
093        throw new PrometheusPropertiesException(
094            PREFIX
095                + "."
096                + MIN_RETENTION_PERIOD_SECONDS
097                + " must not be greater than "
098                + PREFIX
099                + "."
100                + MAX_RETENTION_PERIOD_SECONDS
101                + ".");
102      }
103    }
104
105    return new ExemplarsProperties(
106        minRetentionPeriodSeconds, maxRetentionPeriodSeconds, sampleIntervalMilliseconds);
107  }
108
109  public static Builder builder() {
110    return new Builder();
111  }
112
113  public static class Builder {
114
115    @Nullable private Integer minRetentionPeriodSeconds;
116    @Nullable private Integer maxRetentionPeriodSeconds;
117    @Nullable private Integer sampleIntervalMilliseconds;
118
119    private Builder() {}
120
121    public Builder minRetentionPeriodSeconds(int minRetentionPeriodSeconds) {
122      this.minRetentionPeriodSeconds = minRetentionPeriodSeconds;
123      return this;
124    }
125
126    public Builder maxRetentionPeriodSeconds(int maxRetentionPeriodSeconds) {
127      this.maxRetentionPeriodSeconds = maxRetentionPeriodSeconds;
128      return this;
129    }
130
131    public Builder sampleIntervalMilliseconds(int sampleIntervalMilliseconds) {
132      this.sampleIntervalMilliseconds = sampleIntervalMilliseconds;
133      return this;
134    }
135
136    public ExemplarsProperties build() {
137      return new ExemplarsProperties(
138          minRetentionPeriodSeconds, maxRetentionPeriodSeconds, sampleIntervalMilliseconds);
139    }
140  }
141}