DEV Community

Manoj Sharma
Manoj Sharma

Posted on • Updated on

Spring Boot Actuators: Expose Operational Info

Spring boot has gained a lot of popularity with time, because of its provided features. and now this framework offers solutions for a wide range of enterprise problems and patterns and fits best into every need, It is bundled with a large number of auto configurable libraries/modules to reduce the boiler plate and allow you to focus on your business logic.

Spring boot Actuator is one of the popular feature of Spring Boot for creating production ready applications. Actuator exposes set of endpoints to monitor your application health, view metrics, secure them with spring security and many other features that are necessary for you to declare your application production ready.

Features of Spring Boot Actuator

  1. Spring Boot Actuator module allows you to monitor your applications in 2 ways; either by leveraging HTTP endpoints or JMX (Java Management Extension). Most of the applications leverage HTTP endpoints.
  2. Endpoints: Actuator module is bundled with a rich set of HTTP endpoints to monitor and interact with the application. You can even create custom endpoints to fulfil your needs, and also leverage spring-security to secure actuator endpoints. Few examples are
    • info
    • health
    • metrics
    • beans
    • caches
    • loggers
    • mappings
  3. Metrics: Spring Boot Actuator provides support for a instrumentation library, called Micrometer, which is a vendor neutral application metrics facade that captures and exposes application metrics to different monitoring solutions such as Prometheus, Dynatrace, New Relic, DataDog and many more... It provides interfaces for timers, gauges, counters, distribution summaries, and long task timers with a dimensional data model.
  4. Actuator module is highly (yet simply) configurable and you can utilise your application.[properties|yaml] file to meet most of your customised needs.

Let's build a spring boot application and witness the magic of spring-boot-actuator in action...

Pre-Requisites:

  1. Java installed on your system (JDK 17 recommended), Try SDKMAN to manage your JDK versions.
  2. Spring project with starter-web dependency.
$ curl -G https://start.spring.io/starter.zip \
    -d type=gradle-project \
    -d language=java \
    -d packaging=jar \
    -d javaVersion=17 \
    -d dependencies=web \
    -d name=spring-boot-actuator-example \
    -d baseDir=spring-boot-actuator-example \
    -o starter.zip
$ # You can specify more options using -d option; like groupId, artifactId, packageName
$ unzip starter.zip
$ # Open project in your preferred IDE
Enter fullscreen mode Exit fullscreen mode

Adding Spring Boot Actuator to your application

Add 'spring-boot-starter-actuator' dependency in your build configuration file.
For maven users:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode

For gradle users:

implementation 'org.springframework.boot:spring-boot-starter-actuator'
Enter fullscreen mode Exit fullscreen mode

As soon as you add starter-actuator dependency in your classpath and restart the application (after rebuilding), you can see actuator endpoints are enabled by spring boot. By default, '/actuator' is a base-path for your all actuator endpoints.

INFO 9143 --- [           main] i.c.s.SpringbootActuatorsApplication     : No active profile set, falling back to 1 default profile: "default"
INFO 9143 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
INFO 9143 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
INFO 9143 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.64]
INFO 9143 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
INFO 9143 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 648 ms
INFO 9143 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 1 endpoint(s) beneath base path '/actuator'
INFO 9143 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
INFO 9143 --- [           main] i.c.s.SpringbootActuatorsApplication     : Started SpringbootActuatorsApplication in 1.271 seconds (JVM running for 1.818)
INFO 9143 --- [on(1)-127.0.0.1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
INFO 9143 --- [on(1)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
INFO 9143 --- [on(1)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
Enter fullscreen mode Exit fullscreen mode

The application is started on port 8080, Let's hit '/actuator' endpoint to see all the available actuator endpoints...
SpringBoot Actuator Endpoint

As you can observe there is only '/actuator/health' endpoint is exposed, By default all the other endpoints are disabled, because of security reasons, Since some of the actuator endpoints can expose sensitive data, So be careful...

Let's enable all the endpoints...Update your 'application.properties' file by setting 'management.endpoints.web.exposure.include' property

management.endpoints.web.exposure.include=*
Enter fullscreen mode Exit fullscreen mode

'*' pattern will enable all the endpoints exposed by actuator module. But it is recommended to expose a specific set of endpoints (comma separated list) which is necessary for your operational requirement to avoid any security issues.
NOTE: 'shutdown' endpoint will still be disabled since it is highly critical for your application. It is used to gracefully shutdown your application.
Let's try by hitting 'http://localhost:8080/actuator'

{
   "_links" : {
      "beans" : {
         "href" : "http://localhost:8080/actuator/beans",
         "templated" : false
      },
      "caches" : {
         "href" : "http://localhost:8080/actuator/caches",
         "templated" : false
      },
      "caches-cache" : {
         "href" : "http://localhost:8080/actuator/caches/{cache}",
         "templated" : true
      },
      "conditions" : {
         "href" : "http://localhost:8080/actuator/conditions",
         "templated" : false
      },
      "configprops" : {
         "href" : "http://localhost:8080/actuator/configprops",
         "templated" : false
      },
      "configprops-prefix" : {
         "href" : "http://localhost:8080/actuator/configprops/{prefix}",
         "templated" : true
      },
      "env" : {
         "href" : "http://localhost:8080/actuator/env",
         "templated" : false
      },
      "env-toMatch" : {
         "href" : "http://localhost:8080/actuator/env/{toMatch}",
         "templated" : true
      },
      "health" : {
         "href" : "http://localhost:8080/actuator/health",
         "templated" : false
      },
      "health-path" : {
         "href" : "http://localhost:8080/actuator/health/{*path}",
         "templated" : true
      },
      "heapdump" : {
         "href" : "http://localhost:8080/actuator/heapdump",
         "templated" : false
      },
      "info" : {
         "href" : "http://localhost:8080/actuator/info",
         "templated" : false
      },
      "loggers" : {
         "href" : "http://localhost:8080/actuator/loggers",
         "templated" : false
      },
      "loggers-name" : {
         "href" : "http://localhost:8080/actuator/loggers/{name}",
         "templated" : true
      },
      "mappings" : {
         "href" : "http://localhost:8080/actuator/mappings",
         "templated" : false
      },
      "metrics" : {
         "href" : "http://localhost:8080/actuator/metrics",
         "templated" : false
      },
      "metrics-requiredMetricName" : {
         "href" : "http://localhost:8080/actuator/metrics/{requiredMetricName}",
         "templated" : true
      },
      "scheduledtasks" : {
         "href" : "http://localhost:8080/actuator/scheduledtasks",
         "templated" : false
      },
      "self" : {
         "href" : "http://localhost:8080/actuator",
         "templated" : false
      },
      "threaddump" : {
         "href" : "http://localhost:8080/actuator/threaddump",
         "templated" : false
      }
   }
}
Enter fullscreen mode Exit fullscreen mode

Take a look on this spring documentation for detailed explanation of each endpoint.

*Some more configuration in your application.properties file:

#1. Update default port for actuator endpoints
management.server.port=2121

#2. Update base-path to use **'/manage'** instead of **'/actuator'**
management.endpoints.web.base-path=/manage

#3. Following will ensure include all actuator endpoints except 'mappings' and 'heapdump'
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=mappings,heapdump
Enter fullscreen mode Exit fullscreen mode

Health Endpoint

Health endpoint exposes your application's health to outside world (with useful data), This endpoint becomes more important in distributed systems, where liveness of your one service is dependent on another service like databases, queues or other applications.
Now, Let's try '/actuator/health' endpoint, and see the response
/actuator/health

Right now the only information being returned by health endpoint is whether the application is up or not, by default health endpoint does not show all of the details. This can be enabled (or securely enabled) by setting value of health.show-details attribute.

management.endpoint.health.show-details=always
# Possible values for health.show-details can be one of the following
# never|always|when_authorized
# by default it is set to 'never', 
# 'always' will display all the details,
# 'when_autorized' will display details when requesting user is authorized.
Enter fullscreen mode Exit fullscreen mode

Output (health endpoint with status and diskspace):
Health Endpoint with show-details

Please note Spring Boot Actuator module support configuration update for each endpoint individually by using following pattern.

# Pattern: management.endpoint.{endpoint-name}.{property}=value
# property attribute can vary according to endpoint

management.endpoint.configprops.enabled=true
management.endpoint.info.enabled=false

management.endpoint.beans.cache.time-to-live=10s

management.endpoint.logfile.external-file=~/app.log
Enter fullscreen mode Exit fullscreen mode

Info Endpoint

Let's try '/actuator/info' endpoint now, and see what it returns.
/actuator/info

So, by default info endpoint does not return any useful information, You can customise the response of info endpoint by updating build configurations, Let's walk through how you can configure the info endpoint in build.gradle file.
Maven users can also follow this official spring doc

For gradle users, let's first update the build.gradle file, Add buildInfo task, and update version value.

description = 'Spring Boot Actuator Configuration App'
version = '2.0.0'

springBoot {
    buildInfo() {
        properties {
            additional = [
                    'lastRelease': '1.0.0',
                    'description': rootProject.description
            ]
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Apart from build info, You can also set additional information in application.properties file:

management.info.env.enabled=true

app.cusomInfo=This is Custom Info
info.app.cusomInfo=${app.cusomInfo}
info.app.java-version=${java.version}
info.app.java-vendor=${java.vendor}
info.app.excluded-actuator-enpoints=${management.endpoints.web.exposure.exclude}
Enter fullscreen mode Exit fullscreen mode

Let's now see output of '/actuator/info' endpoint:
/actuator/info additional info

You can observe all the configured information in response. The info endpoint can be extended further to expose git related info (like commit id, branch).

Final Words:

As we can observe just by leveraging the application.[properties|yaml] file, we can fully customise and configure our actuator endpoints to expose useful information. In subsequent posts we will see how we can create custom endpoints, and connect to different monitoring tools using micrometer.

Source Code: manojshr/springboot-actuators

Please share your thoughts in the comments!

Latest comments (1)

Collapse
 
julianhouse profile image
JulianHouse

Thank you very much for your examples. Very well written and clear!!!