io.prometheus.metrics.exporter.httpserver.HttpExchangeAdapter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmx_prometheus_httpserver Show documentation
Show all versions of jmx_prometheus_httpserver Show documentation
See https://github.com/prometheus/jmx_exporter/blob/master/README.md
package io.prometheus.metrics.exporter.httpserver;
import com.sun.net.httpserver.HttpExchange;
import io.prometheus.metrics.exporter.common.PrometheusHttpExchange;
import io.prometheus.metrics.exporter.common.PrometheusHttpRequest;
import io.prometheus.metrics.exporter.common.PrometheusHttpResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HttpExchangeAdapter implements PrometheusHttpExchange {
private final HttpExchange httpExchange;
private final HttpRequest request = new HttpRequest();
private final HttpResponse response = new HttpResponse();
private volatile boolean responseSent = false;
public HttpExchangeAdapter(HttpExchange httpExchange) {
this.httpExchange = httpExchange;
}
public class HttpRequest implements PrometheusHttpRequest {
@Override
public String getQueryString() {
return httpExchange.getRequestURI().getRawQuery();
}
@Override
public Enumeration getHeaders(String name) {
List headers = httpExchange.getRequestHeaders().get(name);
if (headers == null) {
return Collections.emptyEnumeration();
} else {
return Collections.enumeration(headers);
}
}
@Override
public String getMethod() {
return httpExchange.getRequestMethod();
}
@Override
public String getRequestPath() {
URI requestURI = httpExchange.getRequestURI();
String uri = requestURI.toString();
int qx = uri.indexOf('?');
if (qx != -1) {
uri = uri.substring(0, qx);
}
return uri;
}
}
public class HttpResponse implements PrometheusHttpResponse {
@Override
public void setHeader(String name, String value) {
httpExchange.getResponseHeaders().set(name, value);
}
@Override
public OutputStream sendHeadersAndGetBody(int statusCode, int contentLength) throws IOException {
if (responseSent) {
throw new IOException("Cannot send multiple HTTP responses for a single HTTP exchange.");
}
responseSent = true;
httpExchange.sendResponseHeaders(statusCode, contentLength);
return httpExchange.getResponseBody();
}
}
@Override
public HttpRequest getRequest() {
return request;
}
@Override
public HttpResponse getResponse() {
return response;
}
@Override
public void handleException(IOException e) throws IOException {
sendErrorResponseWithStackTrace(e);
}
@Override
public void handleException(RuntimeException e) {
sendErrorResponseWithStackTrace(e);
}
private void sendErrorResponseWithStackTrace(Exception requestHandlerException) {
if (!responseSent) {
responseSent = true;
try {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
printWriter.write("An Exception occurred while scraping metrics: ");
requestHandlerException.printStackTrace(new PrintWriter(printWriter));
byte[] stackTrace = stringWriter.toString().getBytes(StandardCharsets.UTF_8);
httpExchange.getResponseHeaders().set("Content-Type", "text/plain; charset=utf-8");
httpExchange.sendResponseHeaders(500, stackTrace.length);
httpExchange.getResponseBody().write(stackTrace);
} catch (Exception errorWriterException) {
// We want to avoid logging so that we don't mess with application logs when the HTTPServer is used in a Java agent.
// However, if we can't even send an error response to the client there's nothing we can do but logging a message.
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "The Prometheus metrics HTTPServer caught an Exception during scrape and failed to send an error response to the client.", errorWriterException);
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Original Exception that caused the Prometheus scrape error:", requestHandlerException);
}
} else {
// If the exception occurs after response headers have been sent, it's too late to respond with HTTP 500.
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "The Prometheus metrics HTTPServer caught an Exception while trying to send the metrics response.", requestHandlerException);
}
}
@Override
public void close() {
httpExchange.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy