Spring Boot 3 Custom Server Request Observation Convention

Spring Boot 3: How To Override Tags in Server Requests Metrics

Understand how we can override tags in server requests metrics using Spring Custom Server Request Observation Convention. This is useful for customizing the application endpoint metrics. This will override the default tags that are provided by the framework.

Spring Boot 3 Custom Server Request Observation Convention
Spring Boot 3 Custom Server Request Observation Convention

Context

When we add Spring Boot Starter Actuator dependency in our Spring Boot application, we can access the metrics for our application endpoints via the actuator metrics endpoint. In order to access the metrics data, we need to send the GET request specifying the name of metrics we are interested in i.e. in our case server requests metrics.

curl --request GET 'http://localhost:8080/actuator/metrics/http.server.requests'
ShellScript

By default, metrics are available with the name ‘http.server.requests’. This name can be customized by setting one property in the application.properties file.

When we send the request to the above endpoint, by default, we get the following tags in the output:

  • exception: any exceptions that were encountered during the request processing
  • method: HTTP methods
  • uri: endpoints for which we received the requests
  • outcome: whether the request was processed successfully or not
  • status: HTTP status code

Advantages

When we add our custom tags, we can utilize this information to create charts and dashboards displaying information at a more granular level.

Example: For each request, we can add a location tag highlighting the region from where we have received a request. Based on this information, we can create graphs and charts and see from what all regions we are receiving major traffic.



Adding Custom Tags

Note:

Below mentioned steps works only in case of Spring Boot 3.x. For Spring Boot 2.x, kindly refer to article Spring Boot 2: How To Override Tags in Server Request Metrics.

If we want to add our own tags then we can do it with the help of the Spring Custom Server Request Observation Convention. This will override the default tags that are provided by the framework.

Steps:

  1. Create a class that implements the ServerRequestObservationConvention interface.
  2. Provide the implementation for the getLowCardinalityKeyValues method wherein we can add our own tags using KeyValues.
  3. Register this class as Spring bean using @Component annotation.
  4. Also, we can customize the metric name by overriding the getName() method.
import io.micrometer.common.KeyValue;
import io.micrometer.common.KeyValues;
import org.springframework.http.server.observation.ServerHttpObservationDocumentation;
import org.springframework.http.server.observation.ServerRequestObservationContext;
import org.springframework.http.server.observation.ServerRequestObservationConvention;
import org.springframework.stereotype.Component;


/**
 * The type Bootcamp to prod custom server request observation convention.
 * Useful for adding tags in controller metrics in addition to default tags.
 */
@Component
public class BootcampToProdCustomServerRequestObservationConvention implements ServerRequestObservationConvention {

    @Override
    public String getName() {
        // Will be used for the metric name
        // We can customize the metric name as per our own requirement
        return "http.server.requests";
    }

    @Override
    public String getContextualName(ServerRequestObservationContext context) {
        // will be used for the trace name
        return "http " + context.getCarrier().getMethod().toLowerCase();
    }

    @Override
    public KeyValues getLowCardinalityKeyValues(ServerRequestObservationContext context) {
        return KeyValues.of(method(context), status(context), exception(context)).and(additionalTags(context));
    }

    // additional tags that we want to add in metrics
    protected KeyValues additionalTags(ServerRequestObservationContext context) {
        KeyValues keyValues = KeyValues.empty();

        // Optional tag which will be present in metrics only when the condition is evaluated to true
        if (context.getCarrier() != null && context.getCarrier().getParameter("user") != null) {
            keyValues = keyValues.and(KeyValue.of("user", context.getCarrier().getParameter("user")));
        }

        // Custom tag which will be present in all the controller metrics
        keyValues = keyValues.and(KeyValue.of("tag", "value"));

        return keyValues;
    }

    // Adding info related to HTTP Method
    protected KeyValue method(ServerRequestObservationContext context) {
        // You should reuse as much as possible the corresponding ObservationDocumentation for key names
        return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, context.getCarrier().getMethod());
    }

    // Adding info related to HTTP Status
    protected KeyValue status(ServerRequestObservationContext context) {
        // You should reuse as much as possible the corresponding ObservationDocumentation for key names
        return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, Integer.toString(context.getResponse().getStatus()));
    }

    // Adding info related to exception
    protected KeyValue exception(ServerRequestObservationContext context) {
        if (context.getError() != null) {
            // You should reuse as much as possible the corresponding ObservationDocumentation for key names
            return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION, context.getError().getClass().getName());
        } else {
            return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION, "none");
        }
    }

}
Java

We have control over a request object using context.getCarrier(), response object using context.getResponse(), and exception object using context.getError(). Based on this, we can add our own tags.

In the above example, we have added two tags “user” and “tag” wherein the “user” tag is optional and will be added to metrics only if we are receiving requests with the query parameter “user” whereas the “tag” tag will be added to metrics for the all the requests that we have received. Also, we have added tags related to the HTTP method, HTTP status, and exception by extracting the required information from the request, response, and throwable objects that are present in the context.



Output:

Custom Tags Using Custom Server Request Observation Convention
Custom Tags Using Custom Server Request Observation Convention

Source Code

The source code for this example can be found on GitHub. Link: click here



Learn More

#

Curious to Learn Something New?

Check out how we can extend the default tags in Spring Boot 3.

Add a Comment

Your email address will not be published.