Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,27 @@ public class DefaultHandler implements HttpHandler {
private final byte[] responseBytes;
private final String contentType;

public DefaultHandler() {
public DefaultHandler(String metricsPath) {
String metrics = metricsPath.startsWith("/") ? metricsPath.substring(1) : metricsPath;
String responseString =
"<html>\n"
+ "<head><title>Prometheus Java Client</title></head>\n"
+ "<body>\n"
+ "<h1>Prometheus Java Client</h1>\n"
+ "<h2>Metrics Path</h2>\n"
+ "The metrics path is <a href=\"metrics\">/metrics</a>.\n"
+ String.format("The metrics path is <a href=\"%s\">%s</a>.\n", metrics, metricsPath)
+ "<h2>Name Filter</h2>\n"
+ "If you want to scrape only specific metrics, "
+ "use the <tt>name[]</tt> parameter like this:\n"
+ "<ul>\n"
+ "<li><a href=\"metrics?name[]=my_metric\">/metrics?name[]=my_metric</a></li>\n"
+ String.format(
"<li><a href=\"%s?name[]=my_metric\">%s?name[]=my_metric</a></li>\n",
metrics, metricsPath)
+ "</ul>\n"
+ "You can also use multiple <tt>name[]</tt> parameters to query multiple metrics:\n"
+ "<ul>\n"
+ "<li><a href=\"metrics?name[]=my_metric_a&name=my_metrics_b\">"
+ "/metrics?name[]=my_metric_a&amp;name=[]=my_metric_b</a></li>\n"
+ String.format("<li><a href=\"%s?name[]=my_metric_a&name[]=my_metric_b\">", metrics)
+ String.format("%s?name[]=my_metric_a&amp;name[]=my_metric_b</a></li>\n", metricsPath)
+ "</ul>\n"
+ "The <tt>name[]</tt> parameter can be used by the Prometheus server for scraping. "
+ "Add the following snippet to your scrape job configuration in "
Expand All @@ -50,13 +53,17 @@ public DefaultHandler() {
+ "The Prometheus Java metrics library supports a <tt>debug</tt> query parameter "
+ "for viewing the different formats in a Web browser:\n"
+ "<ul>\n"
+ "<li><a href=\"metrics?debug=openmetrics\">/metrics?debug=openmetrics</a>: "
+ String.format(
"<li><a href=\"%s?debug=openmetrics\">%s?debug=openmetrics</a>: ",
metrics, metricsPath)
+ "View OpenMetrics text format.</li>\n"
+ "<li><a href=\"metrics?debug=text\">/metrics?debug=text</a>: "
+ String.format(
"<li><a href=\"%s?debug=text\">%s?debug=text</a>: ", metrics, metricsPath)
+ "View Prometheus text format (this is the default when accessing the "
+ "<a href=\"metrics\">/metrics</a> endpoint with a Web browser).</li>\n"
+ "<li><a href=\"metrics?debug=prometheus-protobuf\">"
+ "/metrics?debug=prometheus-protobuf</a>: "
+ String.format(
"<a href=\"%s\">%s</a> endpoint with a Web browser).</li>\n", metrics, metricsPath)
+ String.format("<li><a href=\"%s?debug=prometheus-protobuf\">", metrics)
+ String.format("%s?debug=prometheus-protobuf</a>: ", metricsPath)
+ "View a text representation of the Prometheus protobuf format.</li>\n"
+ "</ul>\n"
+ "Note that the <tt>debug</tt> parameter is only for viewing different formats in a "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,29 @@ private HTTPServer(
PrometheusRegistry registry,
@Nullable Authenticator authenticator,
@Nullable String authenticatedSubjectAttributeName,
@Nullable HttpHandler defaultHandler) {
@Nullable HttpHandler defaultHandler,
@Nullable String metricsHandlerPath,
@Nullable Boolean registerHealthHandler) {
if (httpServer.getAddress() == null) {
throw new IllegalArgumentException("HttpServer hasn't been bound to an address");
}
this.server = httpServer;
this.executorService = executorService;
String metricsPath = getMetricsPath(metricsHandlerPath);
registerHandler(
"/",
defaultHandler == null ? new DefaultHandler() : defaultHandler,
defaultHandler == null ? new DefaultHandler(metricsPath) : defaultHandler,
authenticator,
authenticatedSubjectAttributeName);
registerHandler(
"/metrics",
metricsPath,
new MetricsHandler(config, registry),
authenticator,
authenticatedSubjectAttributeName);
registerHandler(
"/-/healthy", new HealthyHandler(), authenticator, authenticatedSubjectAttributeName);
if (registerHealthHandler == null || registerHealthHandler) {
registerHandler(
"/-/healthy", new HealthyHandler(), authenticator, authenticatedSubjectAttributeName);
}
try {
// HttpServer.start() starts the HttpServer in a new background thread.
// If we call HttpServer.start() from a thread of the executorService,
Expand All @@ -88,6 +93,16 @@ private HTTPServer(
}
}

private String getMetricsPath(@Nullable String metricsHandlerPath) {
if (metricsHandlerPath == null) {
return "/metrics";
}
if (!metricsHandlerPath.startsWith("/")) {
return "/" + metricsHandlerPath;
}
return metricsHandlerPath;
}

private void registerHandler(
String path,
HttpHandler handler,
Expand Down Expand Up @@ -179,9 +194,11 @@ public static class Builder {
@Nullable private ExecutorService executorService = null;
@Nullable private PrometheusRegistry registry = null;
@Nullable private Authenticator authenticator = null;
@Nullable private String authenticatedSubjectAttributeName = null;
@Nullable private HttpsConfigurator httpsConfigurator = null;
@Nullable private HttpHandler defaultHandler = null;
@Nullable private String authenticatedSubjectAttributeName = null;
@Nullable private String metricsHandlerPath = null;
@Nullable private Boolean registerHealthHandler = null;

private Builder(PrometheusProperties config) {
this.config = config;
Expand Down Expand Up @@ -254,6 +271,18 @@ public Builder defaultHandler(HttpHandler defaultHandler) {
return this;
}

/** Optional: Override default path for the metrics endpoint. Default is {@code /metrics}. */
public Builder metricsHandlerPath(String metricsHandlerPath) {
this.metricsHandlerPath = metricsHandlerPath;
return this;
}

/** Optional: Override if the health handler should be registered. Default is {@code true}. */
public Builder registerHealthHandler(boolean registerHealthHandler) {
this.registerHealthHandler = registerHealthHandler;
return this;
}

/** Build and start the HTTPServer. */
public HTTPServer buildAndStart() throws IOException {
if (registry == null) {
Expand All @@ -275,7 +304,9 @@ public HTTPServer buildAndStart() throws IOException {
registry,
authenticator,
authenticatedSubjectAttributeName,
defaultHandler);
defaultHandler,
metricsHandlerPath,
registerHealthHandler);
}

private InetSocketAddress makeInetSocketAddress() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@ void metrics() throws IOException {
"/metrics");
}

@Test
void metricsCustomPath() throws IOException {
run(
HTTPServer.builder()
.port(0)
.registry(new PrometheusRegistry())
.metricsHandlerPath("/my-metrics")
.executorService(Executors.newFixedThreadPool(1))
.buildAndStart(),
"200",
"/my-metrics");
}

@Test
void registryThrows() throws IOException {
HTTPServer server =
Expand Down Expand Up @@ -147,4 +160,30 @@ void config() throws NoSuchAlgorithmException, IOException {
void health() throws IOException {
run(HTTPServer.builder().port(0).buildAndStart(), "200", "/-/healthy");
}

@Test
void healthEnabled() throws IOException {
HttpHandler handler = exchange -> exchange.sendResponseHeaders(204, -1);
run(
HTTPServer.builder()
.port(0)
.defaultHandler(handler)
.registerHealthHandler(true)
.buildAndStart(),
"200",
"/-/healthy");
}

@Test
void healthDisabled() throws IOException {
HttpHandler handler = exchange -> exchange.sendResponseHeaders(204, -1);
run(
HTTPServer.builder()
.port(0)
.defaultHandler(handler)
.registerHealthHandler(false)
.buildAndStart(),
"204",
"/-/healthy");
}
}