OpenMetrics has been finalized and the Prometheus Java client supports the OpenMetrics data model and text scrape format since its 0.10.0 release. It would be nice if the Prometheus Actuator endpoint could respond with the Prometheus text format or the OpenMetrics text format based on the Accept
header sent, using HTTP content negotiation.
I made an attempt to implement this, but I couldn't figure out a way to do HTTP content negotiation and keep the current portability of the endpoint. It already is a web-only endpoint, but it works on Jersey. Switching to a RestControllerEndpoint
, I was able to achieve the right behavior, except Jersey is not supported.
@GetMapping(produces = {TextFormat.CONTENT_TYPE_004, TextFormat.CONTENT_TYPE_OPENMETRICS_100})
public ResponseEntity<String> scrape(@RequestParam(name = "includedNames", required = false) Set<String> includedNames,
@RequestHeader(name = "Accept", required = false) String acceptHeader) {
try {
Writer writer = new StringWriter();
Enumeration<MetricFamilySamples> samples = (includedNames != null)
? this.collectorRegistry.filteredMetricFamilySamples(includedNames)
: this.collectorRegistry.metricFamilySamples();
String contentType = TextFormat.chooseContentType(acceptHeader);
TextFormat.writeFormat(contentType, writer, samples);
return ResponseEntity.ok().contentType(MediaType.valueOf(contentType)).body(writer.toString());
}
catch (IOException ex) {
// This actually never happens since StringWriter::write() doesn't throw any
// IOException
throw new RuntimeException("Writing metrics failed", ex);
}
}
A generic ReadOperation
can specify the types it produces (so it rejects requests with unsupported Accept
headers), but it has no access to the Accept
header to change the returned content based on it. I'm not sure what the Boot team wants to do, which is why I opted to open an issue over a pull request with the above (also, I wasn't sure of an easy way to test a RestControllerEndpoint
similar to how the current WebEndpoint
is tested).