Spring Boot Actuators: Custom Endpoint
Tags: springboot, java, monitoring, spring
Published: 2023-08-05 09:55:56

In continuation to the blog series on Spring Actuators, In this post, Let's deep dive into more customization we can do with spring actuators.

No doubt, By default, Spring Actuator exposes a wider set of pre-defined endpoints that can be accessed to gather information about your application's health, metrics, configuration, and more. But there are scenarios where you might want to create custom Actuator endpoints to extend the monitoring and management capabilities of your application. 

Here are some benefits and scenarios where custom endpoints can be useful:
- **Administrative Tasks:** You can use custom endpoints to perform administrative tasks on your application. For example, triggering a specific maintenance routine, clearing cache, or reloading configurations can be exposed through custom endpoints.
- **Custom Health Checks:** While Actuator provides a default health check endpoint, And in the last Post we deep dived into customizing your health endpoint. But your application might have specific health checks that are beyond the scope of the built-in checks. Custom health check endpoints allow you to implement and expose these checks.
- **Security and Access Control:** By creating custom endpoints, you have fine-grained control over who can access specific monitoring and management information. This allows you to restrict access to sensitive endpoints, ensuring that only authorized users or systems can interact with them.
- **Third-party Integrations:** If your application relies on external services or APIs, you can create custom endpoints to monitor the health and status of these integrations. This can be especially useful to quickly identify issues with external dependencies.
- **Complex Aggregations:** The default Actuator endpoints provide basic metrics, but in some cases, you might need to perform complex aggregations and calculations to derive meaningful insights.

## Building Custom Endpoint
Now, Let's try to build our own custom HTTP actuator endpoint.

### @Endpoint
**@Endpoint** annotation is a core component of Spring Actuators. Once you annotate your class with @Endpoint annotation and provide `id` field (mandatorily) as custom value, This class will now represent your custom endpoint.
```java
@Component
@Endpoint(id="custom")
public class CustomActuatorEndpoint {
    ...
}
```
> Do not forget to make your endpoint class spring-managed component by defining @Component annoation.

This will make following actuator endpoint available to be served: `http://your-example-web-app:2121/actuator/custom`. Not let's define **Operations** to add the definition for this custom endpoint.

### Endpoint Operations
Spring Boot Actuator endpoints support mainly 3 basic operations to interact with custom endpoints. You can define methods and annotate them with these annotations.

- **@ReadOperation:** @ReadOperation is used to handle HTTP GET requests. It is used to retrieve information from the Actuator endpoint. Typically, this operation is used to expose various metrics, health information, configurations, and other read-only data.

- **@WriteOperation:** This operation type is used to handle HTTP POST requests to modify the state of the application or perform actions that have side effects.

- **@DeleteOperation:** As it states, @DeleteOperation is used to handle HTTP DELETE requests to remove or delete resources from the application. It can be helpful when you want to provide an API for removing resources or performing specific cleanup tasks.

> It is always recommended to secure your actuator endpoint with spring security while exposing sensitive information or performing write/delete operations that alters the state/config of your application.

It is quiet similar to defining an endpoint using Get/Post/Delete Mappings.

### Example Custom Endpoint
Enough Theory 🤔, Let's write a custom actuator endpoint to manage your application release notes.

This is how your `ReleaseNote` data object looks like
```java
public class ReleaseNote {
    private String version;
    private LocalDateTime date;
    private String changeLogData;
    // Constructors
    // Getters/Setters
}
```

Now, Let's write `ReleaseNoteEndpoint` class which uses `ReleaseNotesDataRepository` to manage persistence of your `ReleaseNote` object.



```java
@Component
@Endpoint(id="releaseNotes")
public class ReleaseNotesEndpoint {
    
    @Autowired
    private ReleaseNotesDataRepository releaseNotesDataRepository;

    @ReadOperation
    public List<ReleaseNote> getReleaseNotes() {
        return releaseNotesDataRepository.getReleaseNoteList();
    }

    @WriteOperation
    public ReleaseNote addReleaseNote(String version, String changeLogData) {
        ReleaseNote releaseNote = new ReleaseNote(version, LocalDateTime.now(), changeLogData);
        return releaseNotesDataRepository.addReleaseNote(releaseNote);
    }

    @DeleteOperation
    public void deleteReleaseNote(@Selector String version) {
        releaseNotesDataRepository.deleteReleaseNote(version);
    }
}
```

> Spring Actuator comes with **@Selector** annotation that is used as an argument of an @Endpoint method to indicate the path parameter for your endpoint

Let's play with the new shiny actuator endpoint to manage release notes.
#### Add new Release Note
```bash
$ curl --location --request POST 'http://localhost:2121/actuator/releaseNotes' \
--header 'Content-Type: application/json' \
--data '{
    "version": "1.0",
    "changeLogData": "changeLog"
}' -i

# Response
HTTP/1.1 200 
...
{"version":"1.0","date":"2023-08-05T15:01:37.456528","changeLogData":"v1.0 changeLog"}
```

#### List all Release Notes
```shell
curl --location --request GET 'http://localhost:2121/actuator/releaseNotes' -i

# Response
HTTP/1.1 200 
...
[{"version":"1.0","date":"2023-08-05T15:01:37.456528","changeLogData":"v1.0 changeLog"}]
```
#### Delete Release Note
```shell
curl --location --request DELETE 'http://localhost:2121/actuator/releaseNotes/1.0' -i

# Response
HTTP/1.1 204 
```

### Final Words
Incorporating custom Actuator endpoints into your Spring Boot applications can be really helpful to fulfil your custom needs. These tailored endpoints empower your boot application to extract specific insights, enact administrative tasks, and dynamically adjust configurations. Would love to hear your experience and thoughts!