001package io.prometheus.metrics.config;
002
003import io.prometheus.metrics.annotations.StableApi;
004import java.time.Duration;
005import javax.annotation.Nullable;
006
007@StableApi
008public class ExporterPushgatewayProperties {
009
010  private static final String ADDRESS = "address";
011  private static final String JOB = "job";
012  private static final String SCHEME = "scheme";
013  private static final String ESCAPING_SCHEME = "escaping_scheme";
014  private static final String READ_TIMEOUT = "read_timeout_seconds";
015  private static final String CONNECT_TIMEOUT = "connect_timeout_seconds";
016  private static final String PREFIX = "io.prometheus.exporter.pushgateway";
017  @Nullable private final String scheme;
018  @Nullable private final String address;
019  @Nullable private final String job;
020  @Nullable private final EscapingScheme escapingScheme;
021  @Nullable private final Duration connectTimeout;
022  @Nullable private final Duration readTimeout;
023
024  private ExporterPushgatewayProperties(
025      @Nullable String address,
026      @Nullable String job,
027      @Nullable String scheme,
028      @Nullable EscapingScheme escapingScheme,
029      @Nullable Duration connectTimeout,
030      @Nullable Duration readTimeout) {
031    this.address = address;
032    this.job = job;
033    this.scheme = scheme;
034    this.escapingScheme = escapingScheme;
035    this.connectTimeout = connectTimeout;
036    this.readTimeout = readTimeout;
037  }
038
039  /** Address of the Pushgateway in the form {@code host:port}. Default is {@code localhost:9091} */
040  @Nullable
041  public String getAddress() {
042    return address;
043  }
044
045  /**
046   * {@code job} label for metrics being pushed. Default is the name of the JAR file that is
047   * running.
048   */
049  @Nullable
050  public String getJob() {
051    return job;
052  }
053
054  /**
055   * Scheme to be used when pushing metrics to the pushgateway. Must be "http" or "https". Default
056   * is "http".
057   */
058  @Nullable
059  public String getScheme() {
060    return scheme;
061  }
062
063  /** Escaping scheme to be used when pushing metric data to the pushgateway. */
064  @Nullable
065  public EscapingScheme getEscapingScheme() {
066    return escapingScheme;
067  }
068
069  /** Connection timeout for connections to the Pushgateway. */
070  @Nullable
071  public Duration getConnectTimeout() {
072    return connectTimeout;
073  }
074
075  /** Read timeout for connections to the Pushgateway. */
076  @Nullable
077  public Duration getReadTimeout() {
078    return readTimeout;
079  }
080
081  /**
082   * Note that this will remove entries from {@code propertySource}. This is because we want to know
083   * if there are unused properties remaining after all properties have been loaded.
084   */
085  static ExporterPushgatewayProperties load(PropertySource propertySource)
086      throws PrometheusPropertiesException {
087    String address = Util.loadString(PREFIX, ADDRESS, propertySource);
088    String job = Util.loadString(PREFIX, JOB, propertySource);
089    String scheme = Util.loadString(PREFIX, SCHEME, propertySource);
090    String escapingScheme = Util.loadString(PREFIX, ESCAPING_SCHEME, propertySource);
091    Duration connectTimeout = Util.loadOptionalDuration(PREFIX, CONNECT_TIMEOUT, propertySource);
092    Duration readTimeout = Util.loadOptionalDuration(PREFIX, READ_TIMEOUT, propertySource);
093
094    if (scheme != null) {
095      if (!scheme.equals("http") && !scheme.equals("https")) {
096        throw new PrometheusPropertiesException(
097            String.format(
098                "%s.%s: Illegal value. Expecting 'http' or 'https'. Found: %s",
099                PREFIX, SCHEME, scheme));
100      }
101    }
102
103    return new ExporterPushgatewayProperties(
104        address, job, scheme, parseEscapingScheme(escapingScheme), connectTimeout, readTimeout);
105  }
106
107  private static @Nullable EscapingScheme parseEscapingScheme(@Nullable String scheme) {
108    if (scheme == null) {
109      return null;
110    }
111    switch (scheme) {
112      case "allow-utf-8":
113        return EscapingScheme.ALLOW_UTF8;
114      case "values":
115        return EscapingScheme.VALUE_ENCODING_ESCAPING;
116      case "underscores":
117        return EscapingScheme.UNDERSCORE_ESCAPING;
118      case "dots":
119        return EscapingScheme.DOTS_ESCAPING;
120      default:
121        throw new PrometheusPropertiesException(
122            String.format(
123                "%s.%s: Illegal value. Expecting 'allow-utf-8', 'values', 'underscores', "
124                    + "or 'dots'. Found: %s",
125                PREFIX, ESCAPING_SCHEME, scheme));
126    }
127  }
128
129  public static Builder builder() {
130    return new Builder();
131  }
132
133  public static class Builder {
134    @Nullable private String address;
135    @Nullable private String job;
136    @Nullable private String scheme;
137    @Nullable private EscapingScheme escapingScheme;
138    @Nullable private Duration connectTimeout;
139    @Nullable private Duration readTimeout;
140
141    private Builder() {}
142
143    public Builder address(String address) {
144      this.address = address;
145      return this;
146    }
147
148    public Builder job(String job) {
149      this.job = job;
150      return this;
151    }
152
153    public Builder scheme(String scheme) {
154      this.scheme = scheme;
155      return this;
156    }
157
158    public Builder escapingScheme(EscapingScheme escapingScheme) {
159      this.escapingScheme = escapingScheme;
160      return this;
161    }
162
163    public Builder connectTimeout(Duration connectTimeout) {
164      this.connectTimeout = connectTimeout;
165      return this;
166    }
167
168    public Builder readTimeout(Duration readTimeout) {
169      this.readTimeout = readTimeout;
170      return this;
171    }
172
173    public ExporterPushgatewayProperties build() {
174      return new ExporterPushgatewayProperties(
175          address, job, scheme, escapingScheme, connectTimeout, readTimeout);
176    }
177  }
178}