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