Java: exposing a custom Actuator endpoint with Spring Boot

If you have enabled Actuator in your Spring Boot application, then in addition to the standard endpoints for health and metrics, you can also add your own endpoint to expose custom metrics.

In its simplest form, this is done by adding a @Component and @Endpoint annotation to a custom class that returns the metrics, and annotating the method with @ReadOperation.

And if you would prefer to return data more like your standard web Controller, you can instead annotate the class with @ControllerEndpoint and the methods with @GetMapping, which I will show in this article.

Spring Boot prerequisites

If you are reading this article, I’m assuming you have enabled the Actuator package already, and that you have already proven that you can can reach endpoints such as /actuator and /actuator/health for your Spring Boot web application.

If not, go through this article from Baeldung for the basic setup.

You should be sure that you have included the package in build.gradle

dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-actuator'
   ...
}

Or pom.xml if using Maven.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
  <scope>compile</scope>
</dependency>

And expose the management endpoints in application.properties

management.endpoints.enabled-by-default=true
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details: always

Simple custom Endpoint

To create a basic custom endpoint, annotate a custom class with @Component and @Endpoint

import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.stereotype.Component;

@Component
@Endpoint(id = "simple")
public class SimpleCustomEndpoint {
...

And then annotate methods that return either objects or String with @ReadOperation

// web request to /actuator/simple
@ReadOperation
public Map<String,String> doRead() {
  return keys;
}

// web request to /actuator/simple/<pathName>
@ReadOperation
public String doReadAtPath(@Selector String pathName) {
  return "hello at " + pathName;
}

Here is the full source example, SimpleCustomEndpoint.java

Using ControllerEndpoint

The @Endpoint example above allows you to return simple objects, but if you need custom formatting or content types, then you can use @ControllerEndpoint which provides the same power as you are accustomed to with a Spring web MVC Controller.

Start by annotating the class with @Component and @ControllerEndpoint

@Component
@ControllerEndpoint(id = "prometheus-custom")
public class CustomPrometheusEndpoint {
...

Then annotate the method returning data with @GetMapping

// web request to /actuator/prometheus-custom
@GetMapping(value="/", produces = MediaType.TEXT_PLAIN_VALUE)
public @ResponseBody String customEndPoint() {
...

In this specific case, we want to return a rendered String with Content-Type of “text/plain”, so we use @ResponseBody.  But just like a web MVC controller, you could also return a custom object or ResponseEntity.

Here is the full source to CustomPrometheusEndpoint.java

 

REFERENCES

Spring docs, Actuator

Baeldung, Actuator 2.0

Leo Gutierrez, Writing custom endpoints in Spring Actuator, Endpoint with ReadOperation

codebjoe.de, using maven and git sources for actuator info as well as custom class

javadevjournal.com, custom health endpoint and controller endpoint

masterspringboot.com, adding scrape_config for prometheus for actuator

zetcode.com, the 3 days that responses can be written with Spring Boot

micrometer docs, concepts and code examples