Polish 'Support OpenMetrics text format with Prometheus'

Closes gh-25564
This commit is contained in:
Phillip Webb 2021-03-18 19:12:03 -07:00
parent 11b4a19dee
commit 26ee346510
2 changed files with 34 additions and 26 deletions

View File

@ -24,14 +24,12 @@ import java.util.Set;
import io.prometheus.client.Collector.MetricFamilySamples;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.common.TextFormat;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint;
import org.springframework.lang.Nullable;
import org.springframework.util.MimeType;
/**
* {@link Endpoint @Endpoint} that outputs metrics in a format that can be scraped by the
@ -50,30 +48,19 @@ public class PrometheusScrapeEndpoint {
this.collectorRegistry = collectorRegistry;
}
@ReadOperation(produces = { TextFormat.CONTENT_TYPE_004, TextFormat.CONTENT_TYPE_OPENMETRICS_100 })
public WebEndpointResponse<String> scrape(ProducibleTextFormat producibleTextFormat,
@Nullable Set<String> includedNames) {
@ReadOperation(producesFrom = TextOutputFormat.class)
public WebEndpointResponse<String> scrape(TextOutputFormat format, @Nullable Set<String> includedNames) {
try {
Writer writer = new StringWriter();
Enumeration<MetricFamilySamples> samples = (includedNames != null)
? this.collectorRegistry.filteredMetricFamilySamples(includedNames)
: this.collectorRegistry.metricFamilySamples();
MimeType contentType = producibleTextFormat.getMimeType();
if (producibleTextFormat == ProducibleTextFormat.CONTENT_TYPE_004) {
TextFormat.write004(writer, samples);
}
else if (producibleTextFormat == ProducibleTextFormat.CONTENT_TYPE_OPENMETRICS_100) {
TextFormat.writeOpenMetrics100(writer, samples);
}
else {
throw new RuntimeException("Unsupported text format '" + producibleTextFormat.getMimeType() + "'");
}
return new WebEndpointResponse<>(writer.toString(), contentType);
format.write(writer, samples);
return new WebEndpointResponse<>(writer.toString(), format);
}
catch (IOException ex) {
// This actually never happens since StringWriter::write() doesn't throw any
// IOException
throw new RuntimeException("Writing metrics failed", ex);
// This actually never happens since StringWriter doesn't throw an IOException
throw new IllegalStateException("Writing metrics failed", ex);
}
}

View File

@ -16,39 +16,60 @@
package org.springframework.boot.actuate.metrics.export.prometheus;
import java.io.IOException;
import java.io.Writer;
import java.util.Enumeration;
import io.prometheus.client.Collector.MetricFamilySamples;
import io.prometheus.client.exporter.common.TextFormat;
import org.springframework.boot.actuate.endpoint.http.Producible;
import org.springframework.boot.actuate.endpoint.annotation.Producible;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
/**
* A {@link Producible} for Prometheus's {@link TextFormat}.
* A {@link Producible} enum for supported Prometheus {@link TextFormat}.
*
* @author Andy Wilkinson
* @since 2.5.0
*/
public enum ProducibleTextFormat implements Producible<ProducibleTextFormat> {
public enum TextOutputFormat implements Producible<TextOutputFormat> {
/**
* Openmetrics text version 1.0.0.
*/
CONTENT_TYPE_OPENMETRICS_100(TextFormat.CONTENT_TYPE_OPENMETRICS_100),
CONTENT_TYPE_OPENMETRICS_100(TextFormat.CONTENT_TYPE_OPENMETRICS_100) {
@Override
void write(Writer writer, Enumeration<MetricFamilySamples> samples) throws IOException {
TextFormat.writeOpenMetrics100(writer, samples);
}
},
/**
* Prometheus text version 0.0.4.
*/
CONTENT_TYPE_004(TextFormat.CONTENT_TYPE_004);
CONTENT_TYPE_004(TextFormat.CONTENT_TYPE_004) {
@Override
void write(Writer writer, Enumeration<MetricFamilySamples> samples) throws IOException {
TextFormat.write004(writer, samples);
}
};
private final MimeType mimeType;
ProducibleTextFormat(String mimeType) {
TextOutputFormat(String mimeType) {
this.mimeType = MimeTypeUtils.parseMimeType(mimeType);
}
@Override
public MimeType getMimeType() {
public MimeType getProducedMimeType() {
return this.mimeType;
}
abstract void write(Writer writer, Enumeration<MetricFamilySamples> samples) throws IOException;
}