Adding a new custom module to the Spring Boot application is not so complex. To demonstrate this feature, assume that if a service gets more than two transactions in a minute, then the server status will be set as Out of Service.
In order to customize this, we have to implement the HealthIndicator
interface and override the health
method. The following is a quick and dirty implementation to do the job:
class TPSCounter { LongAdder count; int threshold = 2; Calendar expiry = null; TPSCounter(){ this.count = new LongAdder(); this.expiry = Calendar.getInstance(); this.expiry.add(Calendar.MINUTE, 1); } boolean isExpired(){ return Calendar.getInstance().after(expiry); } boolean isWeak(){ return (count.intValue() > threshold); } void increment(){ count.increment(); } }
The preceding class is a simple POJO class that maintains the transaction counts in the window. The isWeak
method checks whether the transaction in a particular window reached its threshold. The isExpired
method checks whether the current window is expired or not. The increment
method simply increases the counter value.
For the next step, implement our custom health indicator class, TPSHealth
. This is done by extending HealthIndicator
, as follows:
@Component class TPSHealth implements HealthIndicator { TPSCounter counter; @Override public Health health() { boolean health = counter.isWeak(); // perform some specific health check if (health) { return Health.outOfService().withDetail("Too many requests", "OutofService").build(); } return Health.up().build(); } void updateTx(){ if(counter == null || counter.isExpired()){ counter = new TPSCounter(); } counter.increment(); } }
The health
method checks whether the counter is weak or not. A weak counter means the service is handling more transactions than it can handle. If it is weak, it marks the instance as Out of Service.
Finally, we will autowire TPSHealth
into the GreetingController
class and then call health.updateTx()
in the greet
method, as follows:
Greet greet(){ logger.info("Serving Request....!!!"); health.updateTx(); return new Greet("Hello World!"); }
Go to the /health
end point in the HAL browser and take a look at the status of the server.
Now, open another browser, point to http://localhost:8080
, and fire the service twice or thrice. Go back to the /health
endpoint and refresh to see the status. It should be changed to Out of Service.
In this example, as there is no action taken other than collecting the health status, even though the status is Out of Service, new service calls will still go through. However, in the real world, a program should read the /health
endpoint and block further requests from going to this instance.
Similar to health, customization of the metrics is also possible. The following example shows how to add counter service and gauge service, just for demonstration purposes:
@Autowired CounterService counterService; @Autowired GaugeService gaugeService;
Add the following methods in the greet method:
this.counterService.increment("greet.txnCount"); this.gaugeService.submit("greet.customgauge", 1.0);
Restart the server and go to /metrics
to see the new gauge and counter added already reflected there.