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