Spring Boot Actuator A Complete Guide

Hello friends!!! In this article, we’re going to introduce Spring Boot Actuators for collecting metrics about your production grade applications and also talk about some simple ways to work with them in production. Spring Boot Actuator is a sub-project of Spring Boot. It adds several production grade services to your application with little effort on your part. Lets discuss here about spring boot actuator and different types of metrics that can be collected using this feature.

Table of Contents
  1. What Is An Actuator?
  2. How to Enable an Actuator?
  3. Endpoints
  4. Custom Metric Data
  5. Create A New Endpoint
  6. A New Endpoint To List All Endpoints
  7. Actuator Example application
  8. Summary
1. What Is An Actuator?
Spring Boot Actuator is sub-project of Spring Boot and it is one of the nice feature that adds great value to the Spring Boot applications. It adds several production grade services to your application with little effort on your part. There are also has many features added to your application out-of-the-box for managing the service in a production (or other) environment. They’re mainly used to expose different types of information about the running application – health, metrics, info, dump, env etc.

2. How To Enable Spring Boot Actuator?
The spring-boot-actuator module provides all of Spring Boot’s production-ready features. The simplest way to enable the features is to add a dependency to the spring-boot-starter-actuator ‘Starter’.

2.1 In Maven Project
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

2.2 In Gradle Project
dependencies {
    compile("org.springframework.boot:spring-boot-starter-actuator")
}
3. Endpoints
Actuator endpoints allow you to monitor and interact with your application. Spring Boot includes a number of built-in endpoints and you can also add your own. Most endpoints are sensitive – meaning they’re not fully public – while a handful are not: /health and /info.

Here’s some of the most common endpoints Boot provides out of the box:

  • /actuator- Provides a hypermedia-based “discovery page” for the other endpoints. Requires Spring HATEOAS to be on the classpath. Sensitive by Default.
  • /autoconfig- Displays an auto-configuration report showing all auto-configuration candidates and the reason why they ‘were’ or ‘were not’ applied. Sensitive by Default.
  • /beans- Displays a complete list of all the Spring beans in your application. Sensitive by Default.
  • /configprops- This endpoint shows configuration properties used by your application. Sensitive by Default.
  • /dump- Performs a thread dump. Sensitive by Default.
  • /env- Exposes spring’s properties from the configurations. Sensitive by Default.
  • /health – Shows application health information (a simple ‘status’ when accessed over an unauthenticated connection or full message details when authenticated). It is sensitive by default.
  • /info – Displays arbitrary application info. Not sensitive by default.
  • /metrics – Shows ‘metrics’ information for the current application. It is also sensitive by default.
  • /mappings- Displays a list of all @RequestMapping paths. Sensitive by Default.
  • /shutdown- This endpoint allows to shutdown the application. This is not enabled by default. Sensitive by Default.
  • /trace – Displays trace information (by default the last few HTTP requests). Sensitive by Default.
  • /logfile- Provides access to the configured log files (This feature supported since Spring Boot 1.3.0). Sensitive by Default.
  • /flyway- This endpoint provides the details of any flyway database migrations have been applied. Sensitive by Default.
  • /liquibase- This endpoint provides the details of any liquibase database migrations have been applied. Sensitive by Default.
3.1 Customizing Existing Endpoints
Above listed each endpoint can be customized with properties using the following format:
endpoints.[endpoint name].[property to customize]
  • id – by which this endpoint will be accessed over HTTP
  • enabled – if true then it can be accessed otherwise not
  • sensitive – if true then need authorization to show crucial information over HTTP

You can change how those endpoints are exposed using application.properties, the most common settings:
  • management.port=8081 - you can expose those endpoints on port other than the one application is using (8081 here).
  • management.address=127.0.0.1 - you can only allow to access by IP address (localhost here).
  • management.context-path=/actuator - allows you to have those endpoints grouped under specified context path rather than root, i.e. /actuator/health.
  • endpoints.health.enabled=false - allows to enable/disable specified endpoint by name, here /health is disabled.
Securing endpoints
For security purposes, you might choose to expose the actuator endpoints over a non-standard port – the management.port property can easily be used to configure that. The information exposed by endpoints is most of the time sensitive. While /health is usually harmless to be exposed, /metrics would be too much. Fortunately, you can use Spring Security for that purpose.

Adding starter to class path by adding following dependency to pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
You can disable basic security it in application.properties, so that it leaves only the sensitive Actuator endpoints secured and leaves the rest open for access:
security.basic.enabled=false
You can secure these endpoints by defining the default security properties – user name, password and role – in application.properties file:
security.user.name=admin
security.user.password=secret
management.security.role=SUPERUSER
In case you're using the security features across the application and decided to secure those endpoints yourself, you can disable default security for Actuator:
management.security.enabled=false
3.2 Health information- /health Endpoint
Health information can be used to check the status of your running application. It is often used by monitoring software to alert someone if a production system goes down. The default information exposed by the health endpoint depends on how it is accessed.
http://localhost:8080/health
{
"status" : "UP"
}
This health information is collected from all the beans implementing HealthIndicator interface configured in your application context.

3.3 Security with HealthIndicators
Some information returned by HealthIndicator is sensitive in nature – but you can configure endpoints.health.sensitive=false to expose the other information like diskspace, datasource etc.
endpoints.health.sensitive=false
You can write your custom health indicator to provide additional details to the user. The following are the list of health indication implementation classes available for customization:

  • DiskSpaceHealthIndicator
  • DataSourceHealthIndicator
  • MongoHealthIndicator
  • RabbitHealthIndicator
  • SolrHealthIndicator

The basic configurations for health endpoint is:
endpoints.health.id=health
endpoints.health.sensitive=true
endpoints.health.enabled=true
Customized Health checkup:
The basic idea for health checks is that they can provide more insightful information to you on the application's health. Besides checking if the application is UP or DOWN, which is done by default, you can add checks for things like database connectivity or whatever suits you. This is in fact what is being done when you add other Spring Boot starters, as they often provide additional health checks.
/**
 * 
 */
package com.dineshonjava.sba;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;

/**
 * @author Dinesh.Rajput
 *
 */
public class MyAppHealth implements HealthIndicator{

 @Override
 public Health health() {
  int errorCode = check(); // perform some specific health check
  if (errorCode != 0) {
   return Health.down().withDetail("Error Code", errorCode).build();
  }
  return Health.up().build();
 }

 private int check() {
           // Your logic to check health
  return 0;
 }

}
As you can see all it takes is to create a bean implementing HealthIndicator with a method health() returning appropriate Health object. The checks you create will appear on the /health endpoint, so the application can be monitored for them. The output will be:
http://localhost:8080/health
{
status: "UP",
diskSpace: {
status: "UP",
total: 240721588224,
free: 42078715904,
threshold: 10485760
}
}
3.4 Application information- /info Endpoint
Application information exposes various information collected from all InfoContributor beans defined in your ApplicationContext. Spring Boot includes a number of auto-configured InfoContributors and you can also write your own. The default value for sensitive is false. There is no harm in exposing this details as that is common details that has to be exposed to others.

You can also customize the data shown by /info endpoint – for example: Configuration in application.properties file:
{
endpoints.info.id=info
endpoints.info.sensitive=false
endpoints.info.enabled=true

info.app.name=Spring Boot Actuator Application
info.app.description=This is my first Working Spring Actuator Examples
info.app.version=0.0.1-SNAPSHOT
And the sample output:
http://localhost:8080/info
{
{
app: {
version: "0.0.1-SNAPSHOT",
description: "This is my first Working Spring Actuator Examples",
name: "Spring Boot Actuator Application"
}
}
3.5 Metrics Information-/metrics Endpoint
The metrics endpoint is one of the more important endpoints as it gathers and publishes information about OS, JVM and Application level metrics; out of the box, we get things like memory, heap, processors, threads, classes loaded, classes unloaded, thread pools along with some HTTP metrics as well. By default this endpoint is enabled under the HTTP URL /metrics.
he example configuration for this endpoint is:
{
endpoints.metrics.id=metrics
endpoints.metrics.sensitive=true
endpoints.metrics.enabled=true
Here’s what the output of this endpoint looks like out of the box:
http://localhost:8080/metrics
{
{
mem: 55470,
mem.free: 5398,
processors: 4,
instance.uptime: 9452,
uptime: 14466,
systemload.average: -1,
heap.committed: 35020,
heap.init: 16384,
heap.used: 29621,
heap: 253440,
nonheap.committed: 20800,
nonheap.init: 160,
nonheap.used: 20451,
nonheap: 0,
threads.peak: 17,
threads.daemon: 14,
threads.totalStarted: 20,
threads: 16,
classes: 6542,
classes.loaded: 6542,
classes.unloaded: 0,
gc.copy.count: 60,
gc.copy.time: 232,
gc.marksweepcompact.count: 2,
gc.marksweepcompact.time: 61,
httpsessions.max: -1,
httpsessions.active: 0
}

There are following multiple resources matrics exposed by spring boot actualtor
3.5.1. System Metrics
The following system metrics are exposed by Spring Boot:
  • The total system memory in KB (mem)
  • The amount of free memory in KB (mem.free)
  • The number of processors (processors)
  • The system uptime in milliseconds (uptime)
  • The application context uptime in milliseconds (instance.uptime)
  • The average system load (systemload.average)
  • Heap information in KB (heap, heap.committed, heap.init, heap.used)
  • Thread information (threads, thread.peak, thread.daemon)
  • Class load information (classes, classes.loaded, classes.unloaded)
  • Garbage collection information (gc.xxx.count, gc.xxx.time)
3.5.2. DataSource metrics
The following metrics are exposed for each supported DataSource defined in your application:
  • The number of active connections (datasource.xxx.active)
  • The current usage of the connection pool (datasource.xxx.usage).
3.5.3 Cache metrics
The following metrics are exposed for each supported cache defined in your application:
  • The current size of the cache (cache.xxx.size)
  • Hit ratio (cache.xxx.hit.ratio)
  • Miss ratio (cache.xxx.miss.ratio)
By default, Spring Boot provides cache statistics for EhCache, Hazelcast, Infinispan, JCache and Guava.
3.5.4 Tomcat session metrics
If you are using Tomcat as your embedded servlet container, session metrics will automatically be exposed. The httpsessions.active and httpsessions.max keys provide the number of active and maximum sessions.

there are many more matrics you can following spring boot docs for more info http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/.

3.6 Endpoint – Logfile
This endpoint will be automatically enabled if logging.path or logging.file properties are configured in the application.properties file. When you access the logile endpoint, this will return the complete log of the application.

4. Custom Metric Data
To record your own metrics inject a CounterService and/or GaugeService into your bean. The CounterService exposes increment, decrement and reset methods; the GaugeService provides a submit method.

For example – we’ll customize the login flow to record a successful and failed login attempt:
/**
 * 
 */
package com.dineshonjava.sba;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.stereotype.Service;

/**
 * @author Dinesh.Rajput
 *
 */
@Service
public class LoginService {
 
 
 CounterService counterService;
 
 @Autowired
 public LoginService(CounterService counterService) {
        this.counterService = counterService;
        doLogin();
    }
 
 public boolean login(String userName, String password) {
  boolean success;
  if (userName.equals("admin") && "secret".equals(password)) {
   counterService.increment("counter.login.success");
   success = true;
  }
  else {
   counterService.increment("counter.login.failure");
   success = false;
  }
  return success;
 }
 
 private void doLogin() {
  for(int i=0; i<10; i++){
   login("admin", "secret");
  }
  login("admin", "scret");
  login("admin", "scret");
 }
}

Here’s what the output might look like:
......
counter.login.failure: 2,
counter.login.success: 10
....
}
Besides CounterService the other one provided by default is GaugeService that is used to collect a single double value, i.e. a measured execution time. You can also create and use your own implementations of these two.

5. Create A New Endpoint
Besides using the existing endpoints provided by Spring Boot – you can also create an entirely new endpoint. This is useful when you want to expose application details which are an added feature to your application.

/**
 * 
 */
package com.dineshonjava.sba;

import java.util.ArrayList;
import java.util.List;

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

/**
 * @author Dinesh.Rajput
 *
 */
@Component
public class MyCustomEndpoint implements Endpoint<List<String>>{

 @Override
 public String getId() {
  return "myCustomEndpoint";
 }

 @Override
 public List<String> invoke() {
  // Custom logic to build the output
        List<String> list = new ArrayList<String>();
        list.add("App message 1");
        list.add("App message 2");
        list.add("App message 3");
        list.add("App message 4");
        return list;
 }

 @Override
 public boolean isEnabled() {
  return true;
 }

 @Override
 public boolean isSensitive() {
  return true;
 }

}

The way to access this new endpoint is by its id, at /myCustomEndpoint.
http://localhost:8080/myCustomEndpoint
Output:
[
"App message 1",
"App message 2",
"App message 3",
"App message 4"
]
MyCustomEndpoint class implements Endpoint. Any class of type Endpoint will be exposed as an endpoint in the server If you look at the methods, getId(), isEnabled() and isSensitive(), which are the properties that are overridden by the application.properties file. invoke() is the important method responsible for writing the message.

6. A New Endpoint To List All Endpoints
It is quite useful if you have an endpoint to display all the endpoints in a single web page. There is a built-in endpoint /actuator for this purpose, but you have to add HateOAS in the classpath to enable that feature. To implement this one, you’ll need to extend the AbstractEndpoint class:
/**
 * 
 */
package com.dineshonjava.sba;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.stereotype.Component;

/**
 * @author Dinesh.Rajput
 *
 */
@Component
@SuppressWarnings("rawtypes")
public class MyListEndpoints extends AbstractEndpoint<List<Endpoint>>{
 
 List<Endpoint> endpoints;
 
 @Autowired
    public MyListEndpoints(List<Endpoint> endpoints) {
        super("myListEndpoints");
        this.endpoints = endpoints;
    }
 
 @Override
 public List<Endpoint> invoke() {
  return this.endpoints;
 }

}

Here’s how the output will look like:
When you implement the above class, there will be a new endpoint “myListEndpoints” will be registered and exposed to the users. The output will be:
http://localhost:8080/myListEndpoints
[
{
id: "myCustomEndpoint",
enabled: true,
sensitive: true
},
{
id: "mappings",
sensitive: true,
enabled: true
},
{
id: "env",
sensitive: true,
enabled: true
},
{
id: "health",
sensitive: false,
enabled: true,
timeToLive: 1000
},
{
id: "beans",
sensitive: true,
enabled: true
},
{
id: "info",
sensitive: false,
enabled: true
},
{
id: "metrics",
sensitive: false,
enabled: true
},
{
id: "trace",
sensitive: true,
enabled: true
},
{
id: "dump",
sensitive: true,
enabled: true
},
{
id: "autoconfig",
sensitive: true,
enabled: true
},
{
id: "shutdown",
sensitive: true,
enabled: false
},
{
id: "configprops",
sensitive: true,
enabled: true
}
]

7. Actuator Example application
In this section we will make the application which have all required configuration. For creating the application we have used here Spring Boot Web Initializr with Maven Build and following dependencies in pom.xml.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.dineshonjava.sba</groupId>
 <artifactId>SpringBootActuator</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>SpringBootActuator</name>
 <description>SpringBootActuator project for Spring Boot Actuator</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.4.0.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>


</project>

And below is project struct as we have finally.

Spring Boot Actuator

application.properties file for configuration for actuator
#/info endpoint configuration
endpoints.info.id=info
endpoints.info.sensitive=false
endpoints.info.enabled=true
info.app.name=Spring Boot Actuator Application
info.app.description=This is my first Working Spring Actuator Examples
info.app.version=0.0.1-SNAPSHOT

#/metrics endpoint configuration
endpoints.metrics.id=metrics
endpoints.metrics.sensitive=false
endpoints.metrics.enabled=true

#securing endpoints by spring security
security.basic.enabled=true
security.user.name=admin
security.user.password=secret

#/health endpoint configuration (Comment when you are using customized health check)
endpoints.health.id=health
endpoints.health.sensitive=false
endpoints.health.enabled=true

#Management for endpoints
management.port=8080
management.context-path=/
management.security.enabled=true

Whole Code: Here I am not going put all required files for this application you can find whole application from following git repository.
https://github.com/DOJ-SoftwareConsultant/SpringBootActuator


8. Summary:
In this tutorial we had a first look at the interesting Actuator functionality provided by Spring Boot. I have explained about the basic concepts on actuators, endpoints, list of endpoints, creating custom endpoints, health check,metrics and provided a complete working example application for spring boot actuator.

Spring Boot Actuator Video: by Baeldung


Happy Spring Boot Learning!!!



No comments:

Post a Comment