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