Skip to content

Commit

Permalink
Add HTTP response to HttpServerMetricsTagsContributor.Context
Browse files Browse the repository at this point in the history
This is useful for creating tags based on HTTP
response headers for example

Closes: #45717
  • Loading branch information
geoand committed Jan 21, 2025
1 parent 174290c commit 9ac63d5
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 8 deletions.
4 changes: 3 additions & 1 deletion docs/src/main/asciidoc/telemetry-micrometer.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,9 @@ link:https://micrometer.io/docs/concepts[official documentation].

=== Use `HttpServerMetricsTagsContributor` for server HTTP requests

By providing CDI beans that implement `io.quarkus.micrometer.runtime.HttpServerMetricsTagsContributor`, user code can contribute arbitrary tags based on the details of HTTP request
By providing CDI beans that implement `io.quarkus.micrometer.runtime.HttpServerMetricsTagsContributor`, user code can contribute arbitrary tags based on the details of HTTP request and responses.

CAUTION: When creating tags using this interface, it's important to limit the cardinality of the values, otherwise there is a risk of severely degrading the metrics system's capacity.

=== Use `HttpClientMetricsTagsContributor` for client HTTP requests

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.config.MeterFilter;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.spi.observability.HttpResponse;

/**
* Allows code to add additional Micrometer {@link Tags} to the metrics collected for completed HTTP server requests.
Expand All @@ -20,5 +21,7 @@ public interface HttpServerMetricsTagsContributor {

interface Context {
HttpServerRequest request();

HttpResponse response();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public void responseEnd(HttpRequestMetric requestMetric, HttpResponse response,
VertxMetricsTags.outcome(response),
HttpCommonTags.status(response.statusCode()));
if (!httpServerMetricsTagsContributors.isEmpty()) {
HttpServerMetricsTagsContributor.Context context = new DefaultContext(requestMetric.request());
HttpServerMetricsTagsContributor.Context context = new DefaultContext(requestMetric.request(), response);
for (int i = 0; i < httpServerMetricsTagsContributors.size(); i++) {
try {
Tags additionalTags = httpServerMetricsTagsContributors.get(i).contribute(context);
Expand Down Expand Up @@ -258,6 +258,7 @@ public void disconnected(LongTaskTimer.Sample websocketMetric) {
}
}

private record DefaultContext(HttpServerRequest request) implements HttpServerMetricsTagsContributor.Context {
private record DefaultContext(HttpServerRequest request,
HttpResponse response) implements HttpServerMetricsTagsContributor.Context {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus;

import jakarta.inject.Singleton;

import io.micrometer.core.instrument.Tags;
import io.quarkus.micrometer.runtime.HttpServerMetricsTagsContributor;

@Singleton
public class ResponseHeaderTag implements HttpServerMetricsTagsContributor {

@Override
public Tags contribute(Context context) {
var headerValue = context.response().headers().get("foo-response");
String value = "UNSET";
if ((headerValue != null) && !headerValue.isEmpty()) {
value = headerValue;
}
return Tags.of("foo-response", value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.jboss.resteasy.reactive.RestResponse;

import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.smallrye.common.annotation.Blocking;

Expand All @@ -26,9 +28,13 @@ public void trigger() {

@GET
@Path("all")
public void retrieveAll() {
public RestResponse<Object> retrieveAll() {
PanacheQuery<Fruit> query = Fruit.find(
"select name from Fruit");
List<Fruit> all = query.list();

return RestResponse.ResponseBuilder.noContent()
.header("foo-response", "value")
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void testExemplar() {
when().get("/example/prime/7919").then().statusCode(200);

String metricMatch = "http_server_requests_seconds_count{dummy=\"value\",env=\"test\"," +
"env2=\"test\",foo=\"UNSET\",method=\"GET\",outcome=\"SUCCESS\"," +
"env2=\"test\",foo=\"UNSET\",foo_response=\"UNSET\",method=\"GET\",outcome=\"SUCCESS\"," +
"registry=\"prometheus\",status=\"200\",uri=\"/example/prime/{number}\"} 2.0 # {span_id=\"";

await().atMost(5, SECONDS).untilAsserted(() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,15 @@ void testPrometheusScrapeEndpointTextPlain() {
.body(containsString("outcome=\"SUCCESS\""))
.body(containsString("dummy=\"value\""))
.body(containsString("foo=\"bar\""))
.body(containsString("foo_response=\"value\""))
.body(containsString("uri=\"/message/match/{id}/{sub}\""))
.body(containsString("uri=\"/message/match/{other}\""))

.body(containsString(
"http_server_requests_seconds_count{dummy=\"value\",env=\"test\",env2=\"test\",foo=\"UNSET\",method=\"GET\",outcome=\"SUCCESS\",registry=\"prometheus\",status=\"200\",uri=\"/template/path/{value}\""))
"http_server_requests_seconds_count{dummy=\"value\",env=\"test\",env2=\"test\",foo=\"UNSET\",foo_response=\"UNSET\",method=\"GET\",outcome=\"SUCCESS\",registry=\"prometheus\",status=\"200\",uri=\"/template/path/{value}\""))

.body(containsString(
"http_server_requests_seconds_count{dummy=\"value\",env=\"test\",env2=\"test\",foo=\"UNSET\",method=\"GET\",outcome=\"SUCCESS\",registry=\"prometheus\",status=\"200\",uri=\"/root/{rootParam}/sub/{subParam}\""))
"http_server_requests_seconds_count{dummy=\"value\",env=\"test\",env2=\"test\",foo=\"UNSET\",foo_response=\"UNSET\",method=\"GET\",outcome=\"SUCCESS\",registry=\"prometheus\",status=\"200\",uri=\"/root/{rootParam}/sub/{subParam}\""))

// Verify Hibernate Metrics
.body(containsString(
Expand Down Expand Up @@ -233,7 +234,7 @@ void testPrometheusScrapeEndpointOpenMetrics() {
.body(containsString("uri=\"/message/match/{other}\""))

.body(containsString(
"http_server_requests_seconds_count{dummy=\"value\",env=\"test\",env2=\"test\",foo=\"UNSET\",method=\"GET\",outcome=\"SUCCESS\",registry=\"prometheus\",status=\"200\",uri=\"/template/path/{value}\""))
"http_server_requests_seconds_count{dummy=\"value\",env=\"test\",env2=\"test\",foo=\"UNSET\",foo_response=\"UNSET\",method=\"GET\",outcome=\"SUCCESS\",registry=\"prometheus\",status=\"200\",uri=\"/template/path/{value}\""))

// Verify Hibernate Metrics
.body(containsString(
Expand Down

0 comments on commit 9ac63d5

Please sign in to comment.