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