Spring Boot Actuator: Health check, Auditing, Metrics gathering and Monitoring

Spring Boot Actuator module helps you monitor and manage your Spring Boot application by providing production-ready features like health check-up, auditing, metrics gathering, HTTP tracing etc. All of these features can be accessed over JMX or HTTP endpoints.

Actuator also integrates with external application monitoring systems like Prometheus, Graphite, DataDog, Influx, Wavefront, New Relic and many more. These systems provide you with excellent dashboards, graphs, analytics, and alarms to help you monitor and manage your application from one unified interface.

Actuator uses Micrometer, an application metrics facade to integrate with these external application monitoring systems. This makes it super easy to plug-in any application monitoring system with very little configuration.

I’ve divided the Spring Boot Actuator tutorial into two parts -

  • The first part (this article) teaches you how to configure Actuator in a spring boot application and access its features via HTTP endpoints.

  • The second part will teach you how to integrate Actuator with an external application monitoring system.

Creating a Spring Boot application with Actuator

Let’s create a simple Spring Boot application with actuator dependency so that we can explore all its features in this article.

You can create the app using Spring Boot CLI like so -

spring init -d=web,actuator -n=actuator-demo actuator-demo

Alternatively, you can generate the app from Spring Initializr website -

Spring Boot Actuator Metrics Monitoring Demo Application Example

Adding Spring Boot Actuator to an existing application

You can add spring-boot-actuator module to an existing spring boot application using the following dependency.

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

For Gradle, add the dependency like this -

dependencies {
	compile("org.springframework.boot:spring-boot-starter-actuator")
}

Monitoring your application through Actuator Endpoints

Actuator creates several so-called endpoints that can be exposed over HTTP or JMX to let you monitor and interact with your application.

For example, There is a /health endpoint that provides basic information about the application’s health. The /metrics endpoint shows several useful metrics information like JVM memory used, system CPU usage, open files, and much more. The /loggers endpoint shows application’s logs and also lets you change the log level at runtime.

Note that, every actuator endpoint can be explicitly enabled and disabled. Moreover, the endpoints also need to be exposed over HTTP or JMX to make them remotely accessible.

Let’s first run the application and try to access the actuator endpoints that are enabled and exposed over HTTP by default. After that, we’ll learn how to enable more actuator endpoints and also expose them over HTTP.

Type the following command from the root directory of the application to run it -

mvn spring-boot:run

The application will start on port 8080 by default. Once the application has started, you can list all the actuator endpoints exposed over HTTP from the URL http://localhost:8080/actuator.

Spring Boot default exposed Actuator endpoints Let’s explore the health endpoint by opening the http://localhost:8080/actuator/health URL. The endpoint should display the following -

{
    "status": "UP"
}

The status will be UP as long as the application is healthy. It will show DOWN if the application gets unhealthy due to any issue like connectivity with the database or lack of disk space etc. Check out the next section to learn more about how Spring Boot determines the health of your application and how you can tweak it.

The info endpoint (http://localhost:8080/actuator/info) displays general information about your application obtained from build files like META-INF/build-info.properties or Git files like git.properties or through any environment property under the key info. You’ll learn how to tweak the output of this endpoint in the next section.

By default, only the health and info endpoints are exposed over HTTP. That’s why the /actuator page lists only the health and info endpoints. We’ll learn how to expose other endpoints shortly. First, Let’s see what those endpoints are and what do they offer you.

Following is a list of some super useful actuator endpoints. You can see the complete list on the official documentation.

Endpoint IDDescription
auditeventsExposes audit events (e.g. auth_success, order_failed) for your application
infoDisplays information about your application.
healthDisplays your application’s health status.
metricsShows various metrics information of your application.
loggersDisplays and modifies the configured loggers.
logfileReturns the contents of the log file (if logging.file or logging.path properties are set.)
httptraceDisplays HTTP trace info for the last 100 HTTP request/response.
envDisplays current environment properties.
flywayShows details of Flyway database migrations.
liquidbaseShows details of Liquibase database migrations.
shutdownLets you shut down the application gracefully.
mappingsDisplays a list of all @RequestMapping paths.
scheduledtasksDisplays the scheduled tasks in your application.
threaddumpPerforms a thread dump.
heapdumpReturns a GZip compressed JVM heap dump.

Enabling and Disabling Actuator Endpoints

By default, all the endpoints that I listed in the previous section are enabled except the shutdown endpoint.

You can enable or disable an actuator endpoint by setting the property management.endpoint.<id>.enabled to true or false (where id is the identifier for the endpoint).

For example, to enable the shutdown endpoint, add the following to your application.properties file -

management.endpoint.shutdown.enabled=true

Exposing Actuator Endpoints

By default, all the actuator endpoints are exposed over JMX but only the health and info endpoints are exposed over HTTP.

Here is how you can expose actuator endpoints over HTTP and JMX using application properties -

  • Exposing Actuator endpoints over HTTP

    # Use "*" to expose all endpoints, or a comma-separated list to expose selected ones
    management.endpoints.web.exposure.include=health,info 
    management.endpoints.web.exposure.exclude=
  • Exposing Actuator endpoints over JMX

    # Use "*" to expose all endpoints, or a comma-separated list to expose selected ones
    management.endpoints.jmx.exposure.include=*
    management.endpoints.jmx.exposure.exclude=

Let’s expose all actuator endpoints by setting the property management.endpoints.web.exposure.include to * and check the output of http://localhost:8080/actuator page. You’ll notice that the actuator page now lists all the enabled endpoints-

Spring Boot Actuator Endpoints

Exploring common actuator endpoints

/health endpoint

The health endpoint checks the health of your application by combining several health indicators.

Spring Boot Actuator comes with several predefined health indicators like DataSourceHealthIndicator, DiskSpaceHealthIndicator, MongoHealthIndicator, RedisHealthIndicator, CassandraHealthIndicator etc. It uses these health indicators as part of the health check-up process.

For example, If your application uses Redis, the RedisHealthIndicator will be used as part of the health check-up. If your application uses MongoDB, the MongoHealthIndicator will be used as part of the health check-up and so on.

You can also disable a particular health indicator using application properties like so -

management.health.mongo.enabled=false

But by default, all these health indicators are enabled and used as part of the health check-up process.

Displaying detailed health information

The health endpoint only shows a simple UP or DOWN status. To get the complete details including the status of every health indicator that was checked as part of the health check-up process, add the following property in the application.properties file -

# HEALTH ENDPOINT
management.endpoint.health.show-details=always

Once you do that, the health endpoint will display more details like this -

{
   "status":"UP",
   "details":{
      "diskSpace":{
         "status":"UP",
         "details":{
            "total":250790436864,
            "free":100327518208,
            "threshold":10485760
         }
      }
   }
}

The health endpoint now includes the details of the DiskSpaceHealthIndicator which is run as part of the health checkup process.

If your application has a database (say MySQL), the health endpoint will show the status of that as well -

{
   "status":"UP",
   "details":{
      "db":{
         "status":"UP",
         "details":{
            "database":"MySQL",
            "hello":1
         }
      },
      "diskSpace":{
         "status":"UP",
         "details":{
            "total":250790436864,
            "free":100330897408,
            "threshold":10485760
         }
      }
   }
}

If your MySQL server goes down, the status will change to DOWN -

{
   "status":"DOWN",
   "details":{
      "db":{
         "status":"DOWN",
         "details":{
            "error":"org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30006ms."
         }
      },
      "diskSpace":{
         "status":"UP",
         "details":{
            "total":250790436864,
            "free":100324585472,
            "threshold":10485760
         }
      }
   }
}

Creating a Custom Health Indicator

You can also create a custom health indicator by implementing the HealthIndicator interface, or extending the AbstractHealthIndicator class -

package com.example.actuatordemo.health;

import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Component;

@Component
public class CustomHealthIndicator extends AbstractHealthIndicator {

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        // Use the builder to build the health status details that should be reported.
        // If you throw an exception, the status will be DOWN with the exception message.
        
        builder.up()
                .withDetail("app", "Alive and Kicking")
                .withDetail("error", "Nothing! I'm good.");
    }
}

Once you add the above health indicator in your application, the health endpoint will start showing its details as well -

{
   "status":"UP",
   "details":{
      "custom":{
         "status":"UP",
         "details":{
            "app":"Alive and Kicking",
            "error":"Nothing! I'm good."
         }
      },
      "diskSpace":{
         "status":"UP",
         "details":{
            "total":250790436864,
            "free":97949245440,
            "threshold":10485760
         }
      }
   }
}

/metrics endpoint

The /metrics endpoint lists all the metrics that are available for you to track.

Spring Boot Actuator Metrics Endpoint

To get the details of an individual metric, you need to pass the metric name in the URL like this -

http://localhost:8080/actuator/metrics/{MetricName}.

For example, to get the details of system.cpu.usage metric, use the URL http://localhost:8080/actuator/metrics/system.cpu.usage. This will display the details in JSON format like so -

{
   "name":"system.cpu.usage",
   "measurements":[
      {
         "statistic":"VALUE",
         "value":0.11774479321066383
      }
   ],
   "availableTags":[

   ]
}

/loggers endpoint

The loggers endpoint, which can be accessed at http://localhost:8080/actuator/loggers, displays a list of all the configured loggers in your application with their corresponding log levels.

You can also view the details of an individual logger by passing the logger name in the URL like this -

http://localhost:8080/actuator/loggers/{name}.

For example, to get the details of the root logger, use the URL http://localhost:8080/actuator/loggers/root.

{
   "configuredLevel":"INFO",
   "effectiveLevel":"INFO"
}

Changing log levels at runtime.

The loggers endpoint also allows you to change the log level of a given logger in your application at runtime.

For example, To change the log level of the root logger to DEBUG at runtime, make a POST request to the URL http://localhost:8080/actuator/loggers/root with the following payload -

{
   "configuredLevel": "DEBUG"
}

This functionality will really be useful in cases when your application is facing issues in production and you want to enable DEBUG logging for some time to get more details about the issue.

To reset the log-level to the default value, you can pass a value of null in the configuredLevel field.

/info endpoint

The info endpoint displays arbitrary information about your application. It obtains build information from META-INF/build-info.properties file, Git information from git.properties file. It also displays any information available in environment properties under the key info.

You can add properties under the key info in application.properties file like so -

# INFO ENDPOINT CONFIGURATION
info.app.name=@project.name@
info.app.description=@project.description@
info.app.version=@project.version@
info.app.encoding=@project.build.sourceEncoding@
info.app.java.version=@java.version@

Note that, I’m using Spring Boot’s Automatic property expansion feature to expand properties from the maven project.

Once you add the above properties, the info endpoint (http://localhost:8080/actuator/info) will start displaying the information like so -

{
   "app":{
      "name":"actuator-demo",
      "description":"Spring Boot Actuator Demo Project",
      "version":"0.0.1-SNAPSHOT",
      "encoding":"UTF-8",
      "java":{
         "version":"1.8.0_112"
      }
   }
}

Securing Actuator Endpoints with Spring Security

Actuator endpoints are sensitive and must be secured from unauthorized access. If Spring Security is present in your application, then the endpoints are secured by default using a form-based HTTP basic authentication.

If not, you can add spring security to your application using the following dependency -

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

Let’s now see how we can override the default spring security configuration and define our own access rules.

The following example shows a sample spring security configuration that uses a convenient RequestMatcher factory called EndPointRequest provided by spring-boot-actuator module to configure access rules for Actuator endpoints -

package com.example.actuatordemo.config;

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.boot.actuate.context.ShutdownEndpoint;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {

    /*
        This spring security configuration does the following

        1. Restrict access to the Shutdown endpoint to the ACTUATOR_ADMIN role.
        2. Allow access to all other actuator endpoints.
        3. Allow access to static resources.
        4. Allow access to the home page (/).
        5. All other requests need to be authenticated.
        5. Enable http basic authentication to make the configuration complete.
           You are free to use any other form of authentication.
     */

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .requestMatchers(EndpointRequest.to(ShutdownEndpoint.class))
                        .hasRole("ACTUATOR_ADMIN")
                    .requestMatchers(EndpointRequest.toAnyEndpoint())
                        .permitAll()
                    .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
                        .permitAll()
                    .antMatchers("/")
                        .permitAll()
                    .antMatchers("/**")
                        .authenticated()
                .and()
                .httpBasic();
    }
}

To be able to test the above configuration with HTTP basic authentication, you can add a default spring security user in application.properties like so -

# Spring Security Default user name and password
spring.security.user.name=actuator
spring.security.user.password=actuator
spring.security.user.roles=ACTUATOR_ADMIN

You can find the complete source code on Github.

Continue to the Next Part: Spring Boot Actuator metrics monitoring with Prometheus and Grafana

More Learning Resources