Adding production-ready support
We've created a Spring web app with minimal code and released it to production. This is the perfect time to introduce production-grade support features.
There are some questions that often arise in production, and these are as follows:
- What do we do when the system administrator wants to configure his or her monitoring software to ping our app to see if it's up?
- What happens when our manager wants to know the metrics of people hitting our app?
- What are we going to do when the ops center supervisor calls us at 2:00 a.m. and we have to figure out what went wrong?
The last feature we are going to introduce in this chapter is Spring Boot's Actuator module. This module provides some super slick Ops-oriented features that are incredibly valuable in a production environment.
We start by adding this dependency to our build.gradle
as follows:
compile('org.springframework.boot:spring-boot-starter-actuator')
When you run this version of our app, the same business functionality is available that we saw earlier, but there are additional HTTP endpoints; these are listed in the following table:
Actuator Endpoint | Description |
| This reports what Spring Boot did and didn't autoconfigure, and why |
| This reports all the beans configured in the application context (including ours as well as the ones autoconfigured by Boot) |
| This exposes all configuration properties |
| This creates thread dump report |
| This reports on the current system environment |
| This is a simple endpoint to check the life of the app |
| This serves up custom content from the app |
| This shows counters and gauges on web usage |
| This gives us details about all Spring WebFlux routes |
| This shows the details about past requests |
Endpoints, by default, are disabled. We have to opt in. This is accomplished by setting endpoints.{endpoint}.enabled=true
inside src/main/resources/application.properties
, like this:
endpoints.health.enabled=true
This line added to application.properties
mentions the endpoint, health, and enables it. If we restart the application, we can ping for its health, as shown in the next section.
Pinging our app for general health
Each of these endpoints can be visited using our browser or using other tools like curl
:
$ curl localhost:9000/application/health{ "status": "UP", "details": { "mongo": { "status": "UP", "details": { "version": "3.2.2" } }, "diskSpace": { "status": "UP", "details": { "total": 498937626624, "free": 66036432896, "threshold": 10485760 } } } }
This preceding health status gives us the following:
- An overall
UP
status - The status of MongoDB
- The status of the diskspace
When other components are added, they may, optionally, add their own health checks.
This immediately solves our first need listed previously. We can inform the system administrator that he or she can write a management script to interrogate our app's health.
Be warned that each of these endpoints serve up a compact JSON document. Generally speaking, command-line curl
probably isn't the best option. While it's convenient on *nix and Mac systems, the content is dense and hard to read. It's more practical to have the following:
- a JSON plugin installed in our browser (such as JSON Viewer at https://github.com/tulios/json-viewer)
- a script that uses a JSON parsing library if we're writing a management script (such as Groovy's JsonSlurper at http://docs.groovy-lang.org/latest/html/gapi/groovy/json/JsonSlurper.html or JsonPath at https://code.google.com/p/json-path)
Metrics
To really get operational, we need metrics. Most production systems have metrics in one form or another. Thankfully, we don't have to start from scratch. There is a metric endpoint in Spring Boot Actuator. If we add this following setting to application.properties
:
endpoints.metrics.enabled=true
With this property setting, if we restart the application, we can get a quick read out on thing.
Assuming we have JSON Viewer installed, it's easy to surf to http://localhost:9000/application/metrics
and get a listing on all sorts of metrics. We even have counters for every good/bad web hit, broken down on a per-page basis, as shown here:
{ "names": [ "jvm.buffer.memory.used", "jvm.memory.used", "jvm.buffer.count", "logback.events", "process.uptime", "jvm.memory.committed", "jvm.buffer.total.capacity", "jvm.memory.max", "process.starttime", "http.server.requests" ] }
We can visit any one of these metrics by appending it's name to the metrics URL. For example, to view the http.server.requests
, visit http://localhost:9000/application/metrics/http.server.requests
:
{ "name": "http.server.requests", "measurements": [ { "statistic": "TotalTime", "value": 3.53531643E8 }, { "statistic": "Count", "value": 57.0 } ], "availableTags": [ { "tag": "exception", "values": [ "none", "none", "none", "none" ] }, { "tag": "method", "values": [ "GET", "GET", "GET", "GET" ] }, { "tag": "uri", "values": [ "/application/metrics/{requiredMetricName}", "/application/metrics/{requiredMetricName}", "/application/metrics", "/favicon.ico" ] }, { "tag": "status", "values": [ "200", "404", "200", "200" ] } ] }
This provides a basic framework of metrics to satisfy our manager's needs. It's important to understand that metrics gathered by Spring Boot Actuator aren't persistent across application restarts. To gather long-term data, we have to write them elsewhere (http://docs.spring.io/spring-boot/docs/2.0.0.M5/reference/htmlsingle/#production-ready-metrics).
Note
If you have used Spring Boot 1.x, then this may look very different. That's because a newer, more sophisticated version of metrics has arrived--Micrometer. It's currently in development, and may change quite a bit, so stay tuned at http://micrometer.io/, and be sure to follow @micrometerio
on Twitter, as the ability to craft highly detailed and advanced metrics comes to Spring Boot.