Writing custom actuator endpoints

A Spring Boot actuator allows registering custom endpoints that will not only display data but also may update the application's behavior. For that purpose, a Spring bean should be decorated with an @Endpoint annotation. To register read/write operations as an actuator endpoint, the library provides @ReadOperation, @WriteOperation, and @DeleteOperation annotations that are in turn mapped to HTTP GET, POST, and DELETE respectively. Note though, generated REST endpoints consume and produce the following content type:
application/vnd.spring-boot.actuator.v2+json, application/json.

To demonstrate how this feature can be used within the reactive application, let's create a custom endpoint that reports the current server time and the time difference with the Network Time Protocol (NTP) server. Sometimes, such capability helps in resolving issues related to incorrect time due to a server or network misconfiguration. This is especially handy for distributed systems. To do so, we need to register a bean decorated with an @Endpoint annotation and configured ID property (in our case server-time). We will also return the data of interest through a method annotated with @ReadOperation as follows:

@Component
@Endpoint(id = "server-time") // (1)
public class ServerTimeEndpoint {
private Mono<Long> getNtpTimeOffset() { // (2)
// Actual network call to get the current time offset
}

@ReadOperation // (3)
public Mono<Map<String, Object>> reportServerTime() { // (4)
return getNtpTimeOffset() // (5)
.map(timeOffset -> { // (6)
Map<String, Object> rsp = new LinkedHashMap<>(); //
rsp.put("serverTime", Instant.now().toString()); //
rsp.put("ntpOffsetMillis", timeOffset); //
return rsp;
});
}

The preceding code example shows how to create a custom actuator @Endpoint using reactive types from Project Reactor. The aforementioned code sample may be explained as follows:

  1. This is an endpoint class with the @Endpoint annotation. Here, the @Endpoint annotation exposes the ServerTimeEndpoint class as the REST endpoint. In addition, the id parameter of the @Endpoint annotation identifies the URL of the endpoint. In such a combination, the URL is /actuator/server-time.
  2. This is a method definition that asynchronously reports an offset with the current time on the NTP server. The getNtpTimeOffset() method returns Mono<Long>, so it could be composed in a reactive fashion.
  3. Here is a @ReadOperation annotation that marks the reportServerTime() method as a method that should be exposed via Actuator mechanisms as a REST GET operation.
  4. This is the reportServerTime() method that returns a reactive type Mono<Map<String, Object>>, so it may be efficiently used within a Spring WebFlux application.
  5. Here we have a declaration of the asynchronous call to NTP server, the result of which defines the start of a reactive stream.
  6. This is a result transformation operation. When a response arrives, it is transformed with a map() operator, where we fill in the map with a result (current server time and NTP offset) that should be returned to a user. Note that all the fancy techniques for error handling covered in Chapter 4Project Reactor - the Foundation for Reactive Apps can also be used here.
The NTP (http://www.ntp.org) is a very popular protocol for synchronizing computer clocks over a network. NTP servers are publicly available, but be careful not to abuse the system with too many requests because NTP servers may block our application IP address.

With custom endpoints, we may quickly implement dynamic feature toggles, custom request tracking, modes of operation (master/slave), old sessions invalidation, or a lot of other functionalities that are relevant to successful application operations. It is now also possible to do this in a reactive fashion.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.158.32