001package io.prometheus.metrics.expositionformats;
002
003import io.prometheus.metrics.config.EscapingScheme;
004import io.prometheus.metrics.model.snapshots.MetricSnapshots;
005import java.io.IOException;
006import java.io.OutputStream;
007import javax.annotation.Nullable;
008
009/**
010 * Write the Prometheus protobuf format as defined in <a
011 * href="https://github.com/prometheus/client_model/tree/master/io/prometheus/client">github.com/prometheus/client_model</a>.
012 *
013 * <p>As of today, this is the only exposition format that supports native histograms.
014 */
015public class PrometheusProtobufWriter implements ExpositionFormatWriter {
016
017  @Nullable private static final ExpositionFormatWriter DELEGATE = createProtobufWriter();
018
019  public static final String CONTENT_TYPE =
020      "application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; "
021          + "encoding=delimited";
022
023  @Nullable
024  private static ExpositionFormatWriter createProtobufWriter() {
025    try {
026      return Class.forName(
027              "io.prometheus.metrics.expositionformats.internal.PrometheusProtobufWriterImpl")
028          .asSubclass(ExpositionFormatWriter.class)
029          .getDeclaredConstructor()
030          .newInstance();
031    } catch (Exception e) {
032      // not in classpath
033      return null;
034    }
035  }
036
037  @Override
038  public boolean accepts(@Nullable String acceptHeader) {
039    if (acceptHeader == null) {
040      return false;
041    } else {
042      return acceptHeader.contains("application/vnd.google.protobuf")
043          && acceptHeader.contains("proto=io.prometheus.client.MetricFamily");
044    }
045  }
046
047  @Override
048  public String getContentType() {
049    return CONTENT_TYPE;
050  }
051
052  @Override
053  public boolean isAvailable() {
054    return DELEGATE != null;
055  }
056
057  @Override
058  public String toDebugString(MetricSnapshots metricSnapshots, EscapingScheme escapingScheme) {
059    return getDelegate().toDebugString(metricSnapshots, escapingScheme);
060  }
061
062  @Override
063  public void write(
064      OutputStream out, MetricSnapshots metricSnapshots, EscapingScheme escapingScheme)
065      throws IOException {
066    getDelegate().write(out, metricSnapshots, escapingScheme);
067  }
068
069  private ExpositionFormatWriter getDelegate() {
070    if (DELEGATE == null) {
071      throw new UnsupportedOperationException("Prometheus protobuf writer not available");
072    }
073    return DELEGATE;
074  }
075}