001package io.prometheus.metrics.exporter.httpserver;
002
003import com.sun.net.httpserver.HttpExchange;
004import com.sun.net.httpserver.HttpHandler;
005import java.io.IOException;
006import java.nio.charset.StandardCharsets;
007
008/** Handler for the / endpoint */
009public class DefaultHandler implements HttpHandler {
010
011  private final byte[] responseBytes;
012  private final String contentType;
013
014  public DefaultHandler(String metricsPath) {
015    String metrics = metricsPath.startsWith("/") ? metricsPath.substring(1) : metricsPath;
016    String responseString =
017        "<html>\n"
018            + "<head><title>Prometheus Java Client</title></head>\n"
019            + "<body>\n"
020            + "<h1>Prometheus Java Client</h1>\n"
021            + "<h2>Metrics Path</h2>\n"
022            + String.format("The metrics path is <a href=\"%s\">%s</a>.\n", metrics, metricsPath)
023            + "<h2>Name Filter</h2>\n"
024            + "If you want to scrape only specific metrics, "
025            + "use the <tt>name[]</tt> parameter like this:\n"
026            + "<ul>\n"
027            + String.format(
028                "<li><a href=\"%s?name[]=my_metric\">%s?name[]=my_metric</a></li>\n",
029                metrics, metricsPath)
030            + "</ul>\n"
031            + "You can also use multiple <tt>name[]</tt> parameters to query multiple metrics:\n"
032            + "<ul>\n"
033            + String.format("<li><a href=\"%s?name[]=my_metric_a&name[]=my_metric_b\">", metrics)
034            + String.format("%s?name[]=my_metric_a&amp;name[]=my_metric_b</a></li>\n", metricsPath)
035            + "</ul>\n"
036            + "The <tt>name[]</tt> parameter can be used by the Prometheus server for scraping. "
037            + "Add the following snippet to your scrape job configuration in "
038            + "<tt>prometheus.yaml</tt>:\n"
039            + "<pre>\n"
040            + "params:\n"
041            + "    name[]:\n"
042            + "        - my_metric_a\n"
043            + "        - my_metric_b\n"
044            + "</pre>\n"
045            + "<h2>Debug Parameter</h2>\n"
046            + "The Prometheus Java metrics library supports multiple exposition formats.\n"
047            + "The Prometheus server sends the <tt>Accept</tt> header "
048            + "to indicate which format it accepts.\n"
049            + "By default, the Prometheus server accepts OpenMetrics text format, "
050            + "unless the Prometheus server is started with feature flag "
051            + "<tt>--enable-feature=native-histograms</tt>,\n"
052            + "in which case the default is Prometheus protobuf.\n"
053            + "The Prometheus Java metrics library supports a <tt>debug</tt> query parameter "
054            + "for viewing the different formats in a Web browser:\n"
055            + "<ul>\n"
056            + String.format(
057                "<li><a href=\"%s?debug=openmetrics\">%s?debug=openmetrics</a>: ",
058                metrics, metricsPath)
059            + "View OpenMetrics text format.</li>\n"
060            + String.format(
061                "<li><a href=\"%s?debug=text\">%s?debug=text</a>: ", metrics, metricsPath)
062            + "View Prometheus text format (this is the default when accessing the "
063            + String.format(
064                "<a href=\"%s\">%s</a> endpoint with a Web browser).</li>\n", metrics, metricsPath)
065            + String.format("<li><a href=\"%s?debug=prometheus-protobuf\">", metrics)
066            + String.format("%s?debug=prometheus-protobuf</a>: ", metricsPath)
067            + "View a text representation of the Prometheus protobuf format.</li>\n"
068            + "</ul>\n"
069            + "Note that the <tt>debug</tt> parameter is only for viewing different formats in a "
070            + "Web browser, it should not be used by the Prometheus server for scraping. "
071            + "The Prometheus server uses the <tt>Accept</tt> "
072            + "header for indicating which format it accepts.\n"
073            + "</body>\n"
074            + "</html>\n";
075    this.responseBytes = responseString.getBytes(StandardCharsets.UTF_8);
076    this.contentType = "text/html; charset=utf-8";
077  }
078
079  @Override
080  public void handle(HttpExchange exchange) throws IOException {
081    try {
082      exchange.getResponseHeaders().set("Content-Type", contentType);
083      exchange.getResponseHeaders().set("Content-Length", Integer.toString(responseBytes.length));
084      exchange.sendResponseHeaders(200, responseBytes.length);
085      exchange.getResponseBody().write(responseBytes);
086    } finally {
087      exchange.close();
088    }
089  }
090}