001package io.prometheus.metrics.expositionformats;
002
003import io.prometheus.metrics.config.ExporterProperties;
004import io.prometheus.metrics.config.OpenMetrics2Properties;
005import io.prometheus.metrics.config.PrometheusProperties;
006import javax.annotation.Nullable;
007
008public class ExpositionFormats {
009
010  private final PrometheusProtobufWriter prometheusProtobufWriter;
011  private final PrometheusTextFormatWriter prometheusTextFormatWriter;
012  private final OpenMetricsTextFormatWriter openMetricsTextFormatWriter;
013  private final OpenMetrics2TextFormatWriter openMetrics2TextFormatWriter;
014
015  private ExpositionFormats(
016      PrometheusProtobufWriter prometheusProtobufWriter,
017      PrometheusTextFormatWriter prometheusTextFormatWriter,
018      OpenMetricsTextFormatWriter openMetricsTextFormatWriter,
019      OpenMetrics2TextFormatWriter openMetrics2TextFormatWriter) {
020    this.prometheusProtobufWriter = prometheusProtobufWriter;
021    this.prometheusTextFormatWriter = prometheusTextFormatWriter;
022    this.openMetricsTextFormatWriter = openMetricsTextFormatWriter;
023    this.openMetrics2TextFormatWriter = openMetrics2TextFormatWriter;
024  }
025
026  public static ExpositionFormats init() {
027    return init(PrometheusProperties.get());
028  }
029
030  @SuppressWarnings("deprecation")
031  public static ExpositionFormats init(PrometheusProperties properties) {
032    ExporterProperties exporterProps = properties.getExporterProperties();
033    OpenMetrics2Properties om2Props = properties.getOpenMetrics2Properties();
034
035    return new ExpositionFormats(
036        new PrometheusProtobufWriter(),
037        PrometheusTextFormatWriter.builder()
038            .setIncludeCreatedTimestamps(exporterProps.getIncludeCreatedTimestamps())
039            .setTimestampsInMs(exporterProps.getPrometheusTimestampsInMs())
040            .build(),
041        OpenMetricsTextFormatWriter.builder()
042            .setCreatedTimestampsEnabled(exporterProps.getIncludeCreatedTimestamps())
043            .setExemplarsOnAllMetricTypesEnabled(exporterProps.getExemplarsOnAllMetricTypes())
044            .build(),
045        OpenMetrics2TextFormatWriter.builder()
046            .setOpenMetrics2Properties(om2Props)
047            .setCreatedTimestampsEnabled(exporterProps.getIncludeCreatedTimestamps())
048            .setExemplarsOnAllMetricTypesEnabled(exporterProps.getExemplarsOnAllMetricTypes())
049            .build());
050  }
051
052  /**
053   * @deprecated Use {@link #init(PrometheusProperties)} instead.
054   */
055  @Deprecated
056  @SuppressWarnings({"InlineMeSuggester"})
057  public static ExpositionFormats init(ExporterProperties properties) {
058    return init(PrometheusProperties.builder().exporterProperties(properties).build());
059  }
060
061  public ExpositionFormatWriter findWriter(@Nullable String acceptHeader) {
062    if (prometheusProtobufWriter.accepts(acceptHeader)) {
063      return prometheusProtobufWriter;
064    }
065
066    if (isOpenMetrics2Enabled() && openMetrics2TextFormatWriter.accepts(acceptHeader)) {
067      if (openMetrics2TextFormatWriter.getOpenMetrics2Properties().getContentNegotiation()) {
068        String version = parseOpenMetricsVersion(acceptHeader);
069        if ("2.0.0".equals(version)) {
070          return openMetrics2TextFormatWriter;
071        }
072        // version=1.0.0 or no version: fall through to OM1.
073      } else {
074        // contentNegotiation=false: OM2 handles all OpenMetrics requests.
075        return openMetrics2TextFormatWriter;
076      }
077    }
078
079    if (openMetricsTextFormatWriter.accepts(acceptHeader)) {
080      return openMetricsTextFormatWriter;
081    }
082
083    return prometheusTextFormatWriter;
084  }
085
086  private boolean isOpenMetrics2Enabled() {
087    return openMetrics2TextFormatWriter.getOpenMetrics2Properties().getEnabled();
088  }
089
090  public PrometheusProtobufWriter getPrometheusProtobufWriter() {
091    return prometheusProtobufWriter;
092  }
093
094  public PrometheusTextFormatWriter getPrometheusTextFormatWriter() {
095    return prometheusTextFormatWriter;
096  }
097
098  public OpenMetricsTextFormatWriter getOpenMetricsTextFormatWriter() {
099    return openMetricsTextFormatWriter;
100  }
101
102  public OpenMetrics2TextFormatWriter getOpenMetrics2TextFormatWriter() {
103    return openMetrics2TextFormatWriter;
104  }
105
106  @Nullable
107  private static String parseOpenMetricsVersion(@Nullable String acceptHeader) {
108    if (acceptHeader == null) {
109      return null;
110    }
111    for (String mediaType : acceptHeader.split(",")) {
112      if (mediaType.contains("application/openmetrics-text")) {
113        for (String param : mediaType.split(";")) {
114          String[] tokens = param.split("=");
115          if (tokens.length == 2) {
116            String key = tokens[0].trim();
117            String value = tokens[1].trim();
118            if (key.equals("version")) {
119              return value;
120            }
121          }
122        }
123        return null;
124      }
125    }
126    return null;
127  }
128}