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            Util.invalidValueMessage(
098                PREFIX + "." + SCHEME, "Illegal value. Expecting 'http' or 'https'."));
099      }
100    }
101
102    return new ExporterPushgatewayProperties(
103        address, job, scheme, parseEscapingScheme(escapingScheme), connectTimeout, readTimeout);
104  }
105
106  private static @Nullable EscapingScheme parseEscapingScheme(@Nullable String scheme) {
107    if (scheme == null) {
108      return null;
109    }
110    switch (scheme) {
111      case "allow-utf-8":
112        return EscapingScheme.ALLOW_UTF8;
113      case "values":
114        return EscapingScheme.VALUE_ENCODING_ESCAPING;
115      case "underscores":
116        return EscapingScheme.UNDERSCORE_ESCAPING;
117      case "dots":
118        return EscapingScheme.DOTS_ESCAPING;
119      default:
120        throw new PrometheusPropertiesException(
121            Util.invalidValueMessage(
122                PREFIX + "." + ESCAPING_SCHEME,
123                "Illegal value. Expecting 'allow-utf-8', 'values', 'underscores', or 'dots'."));
124    }
125  }
126
127  public static Builder builder() {
128    return new Builder();
129  }
130
131  public static class Builder {
132    @Nullable private String address;
133    @Nullable private String job;
134    @Nullable private String scheme;
135    @Nullable private EscapingScheme escapingScheme;
136    @Nullable private Duration connectTimeout;
137    @Nullable private Duration readTimeout;
138
139    private Builder() {}
140
141    public Builder address(String address) {
142      this.address = address;
143      return this;
144    }
145
146    public Builder job(String job) {
147      this.job = job;
148      return this;
149    }
150
151    public Builder scheme(String scheme) {
152      this.scheme = scheme;
153      return this;
154    }
155
156    public Builder escapingScheme(EscapingScheme escapingScheme) {
157      this.escapingScheme = escapingScheme;
158      return this;
159    }
160
161    public Builder connectTimeout(Duration connectTimeout) {
162      this.connectTimeout = connectTimeout;
163      return this;
164    }
165
166    public Builder readTimeout(Duration readTimeout) {
167      this.readTimeout = readTimeout;
168      return this;
169    }
170
171    public ExporterPushgatewayProperties build() {
172      return new ExporterPushgatewayProperties(
173          address, job, scheme, escapingScheme, connectTimeout, readTimeout);
174    }
175  }
176}