Skip to content

Commit

Permalink
Make /metrics the only Prometheus metrics endpoint (#6476)
Browse files Browse the repository at this point in the history
Signed-off-by: Fabian Stäber <fabian@fstab.de>
Co-authored-by: Jack Berg <jberg@newrelic.com>
  • Loading branch information
fstab and jack-berg authored May 29, 2024
1 parent 0f99d70 commit 7da7037
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

package io.opentelemetry.exporter.prometheus;

import com.sun.net.httpserver.HttpHandler;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.common.export.MemoryMode;
import io.opentelemetry.sdk.internal.DaemonThreadFactory;
Expand All @@ -18,7 +19,6 @@
import io.opentelemetry.sdk.metrics.export.CollectionRegistration;
import io.opentelemetry.sdk.metrics.export.MetricReader;
import io.prometheus.metrics.exporter.httpserver.HTTPServer;
import io.prometheus.metrics.exporter.httpserver.MetricsHandler;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
import java.io.IOException;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -64,7 +64,8 @@ public static PrometheusHttpServerBuilder builder() {
PrometheusRegistry prometheusRegistry,
boolean otelScopeEnabled,
@Nullable Predicate<String> allowedResourceAttributesFilter,
MemoryMode memoryMode) {
MemoryMode memoryMode,
@Nullable HttpHandler defaultHandler) {
this.builder = builder;
this.prometheusMetricReader =
new PrometheusMetricReader(otelScopeEnabled, allowedResourceAttributesFilter);
Expand All @@ -86,7 +87,7 @@ public static PrometheusHttpServerBuilder builder() {
.port(port)
.executorService(executor)
.registry(prometheusRegistry)
.defaultHandler(new MetricsHandler(prometheusRegistry))
.defaultHandler(defaultHandler)
.buildAndStart();
} catch (IOException e) {
throw new UncheckedIOException("Could not create Prometheus HTTP server", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static io.opentelemetry.api.internal.Utils.checkArgument;
import static java.util.Objects.requireNonNull;

import com.sun.net.httpserver.HttpHandler;
import io.opentelemetry.sdk.common.export.MemoryMode;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
import java.util.concurrent.ExecutorService;
Expand All @@ -29,6 +30,7 @@ public final class PrometheusHttpServerBuilder {
@Nullable private Predicate<String> allowedResourceAttributesFilter;
@Nullable private ExecutorService executor;
private MemoryMode memoryMode = DEFAULT_MEMORY_MODE;
@Nullable private HttpHandler defaultHandler;

PrometheusHttpServerBuilder() {}

Expand Down Expand Up @@ -107,6 +109,23 @@ public PrometheusHttpServerBuilder setMemoryMode(MemoryMode memoryMode) {
return this;
}

/**
* Override the default handler for serving the "/", "/**" endpoint.
*
* <p>This can be used to serve metrics on additional paths besides the default "/metrics". For
* example: <code>
* PrometheusHttpServer.builder()
* .setPrometheusRegistry(prometheusRegistry)
* .setDefaultHandler(new MetricsHandler(prometheusRegistry))
* .build()
* </code>
*/
public PrometheusHttpServerBuilder setDefaultHandler(HttpHandler defaultHandler) {
requireNonNull(defaultHandler, "defaultHandler");
this.defaultHandler = defaultHandler;
return this;
}

/**
* Returns a new {@link PrometheusHttpServer} with the configuration of this builder which can be
* registered with a {@link io.opentelemetry.sdk.metrics.SdkMeterProvider}.
Expand All @@ -120,6 +139,7 @@ public PrometheusHttpServer build() {
prometheusRegistry,
otelScopeEnabled,
allowedResourceAttributesFilter,
memoryMode);
memoryMode,
defaultHandler);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.opentelemetry.sdk.metrics.internal.data.ImmutableSumData;
import io.opentelemetry.sdk.resources.Resource;
import io.prometheus.metrics.exporter.httpserver.HTTPServer;
import io.prometheus.metrics.exporter.httpserver.MetricsHandler;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
import java.io.ByteArrayInputStream;
import java.io.IOException;
Expand Down Expand Up @@ -229,7 +230,7 @@ void fetchOpenMetrics() {
void fetchFiltered() {
AggregatedHttpResponse response =
client
.get("/?name[]=grpc_name_unit_total&name[]=bears_total&name[]=target_info")
.get("/metrics?name[]=grpc_name_unit_total&name[]=bears_total&name[]=target_info")
.aggregate()
.join();
assertThat(response.status()).isEqualTo(HttpStatus.OK);
Expand All @@ -245,6 +246,47 @@ void fetchFiltered() {
+ "target_info{kr=\"vr\"} 1\n");
}

@Test
void fetchOverrideDefaultHandler() {
PrometheusRegistry registry = new PrometheusRegistry();
try (PrometheusHttpServer prometheusServer =
PrometheusHttpServer.builder()
.setHost("localhost")
.setPort(0)
.setPrometheusRegistry(registry)
// Set the default handler to serve metrics on /**
.setDefaultHandler(new MetricsHandler(registry))
.build()) {
prometheusServer.register(
new CollectionRegistration() {
@Override
public Collection<MetricData> collectAllMetrics() {
return metricData.get();
}
});
WebClient client =
WebClient.builder("http://localhost:" + prometheusServer.getAddress().getPort())
.decorator(RetryingClient.newDecorator(RetryRule.failsafe()))
.build();

// Fetch metrics from / instead of /metrics
AggregatedHttpResponse response = client.get("/").aggregate().join();
assertThat(response.status()).isEqualTo(HttpStatus.OK);
assertThat(response.headers().get(HttpHeaderNames.CONTENT_TYPE))
.isEqualTo("text/plain; version=0.0.4; charset=utf-8");
assertThat(response.contentUtf8())
.isEqualTo(
"# HELP grpc_name_unit_total long_description\n"
+ "# TYPE grpc_name_unit_total counter\n"
+ "grpc_name_unit_total{kp=\"vp\",otel_scope_name=\"grpc\",otel_scope_version=\"version\"} 5.0\n"
+ "# HELP http_name_unit_total double_description\n"
+ "# TYPE http_name_unit_total counter\n"
+ "http_name_unit_total{kp=\"vp\",otel_scope_name=\"http\",otel_scope_version=\"version\"} 3.5\n"
+ "# TYPE target_info gauge\n"
+ "target_info{kr=\"vr\"} 1\n");
}
}

@SuppressWarnings("resource")
@Test
void fetchPrometheusCompressed() throws IOException {
Expand Down Expand Up @@ -275,7 +317,7 @@ void fetchPrometheusCompressed() throws IOException {
@SuppressWarnings("resource")
@Test
void fetchHead() {
AggregatedHttpResponse response = client.head("/").aggregate().join();
AggregatedHttpResponse response = client.head("/metrics").aggregate().join();
assertThat(response.status()).isEqualTo(HttpStatus.OK);
assertThat(response.headers().get(HttpHeaderNames.CONTENT_TYPE))
.isEqualTo("text/plain; version=0.0.4; charset=utf-8");
Expand Down

0 comments on commit 7da7037

Please sign in to comment.