Groovy

Grails Goodness: Adding Health Check Indicators

With Grails 3 we also get Spring Boot Actuator. We can use Spring Boot Actuator to add some production-ready features for monitoring and managing our Grails application. One of the features is the addition of some endpoints with information about our application. By default we already have a /health endpoint when we start a Grails (3+) application. It gives back a JSON response with status UP. Let’s expand this endpoint and add a disk space, database and url health check indicator.

We can set the application property endpoints.health.sensitive to false (securing these endpoints will be another blog post) and we automatically get a disk space health indicator. The default threshold is set to 10MB, so when the disk space is lower than 10MB the status is set to DOWN. The following snippet shows the change in the grails-app/conf/application.yml to set the property:

1
2
3
4
5
6
...
---
endpoints:
    health:
        sensitive: false
...

If we invoke the /health endpoint we get the following output:

1
2
3
4
5
6
7
8
{
    "status": "UP",
    "diskSpace": {
        "status": "UP",
        "free": 97169154048,
        "threshold": 10485760
    }
}

If we want to change the threshold we can create a Spring bean of type DiskSpaceHealthIndicatorProperties and name diskSpaceHealthIndicatorProperties to override the default bean. Since Grails 3 we can override doWithSpring method in the Application class to define Spring beans:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
package healthcheck
 
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.boot.actuate.health.DiskSpaceHealthIndicatorProperties
 
class Application extends GrailsAutoConfiguration {
 
    static void main(String[] args) {
        GrailsApp.run(Application)
    }
 
    @Override
    Closure doWithSpring() {
        { ->
            diskSpaceHealthIndicatorProperties(DiskSpaceHealthIndicatorProperties) {
                // Set threshold to 250MB.
                threshold = 250 * 1024 * 1024
            }
        }
    }
}

Spring Boot Actuator already contains implementations for checking SQL databases, Mongo, Redis, Solr and RabbitMQ. We can activate those when we add them as Spring beans to our application context. Then they are automatically picked up and added to the results of the /health endpoint. In the following example we create a Spring bean databaseHealth of type DataSourceHealthIndicator:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package healthcheck
 
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.boot.actuate.health.DataSourceHealthIndicator
import org.springframework.boot.actuate.health.DiskSpaceHealthIndicatorProperties
 
class Application extends GrailsAutoConfiguration {
 
    static void main(String[] args) {
        GrailsApp.run(Application)
    }
 
    @Override
    Closure doWithSpring() {
        { ->
            // Configure data source health indicator based
            // on the dataSource in the application context.
            databaseHealthCheck(DataSourceHealthIndicator, dataSource)
 
            diskSpaceHealthIndicatorProperties(DiskSpaceHealthIndicatorProperties) {
                threshold = 250 * 1024 * 1024
            }
        }
    }
}

To create our own health indicator class we must implement the HealthIndicator interface. The easiest way is to extend the AbstractHealthIndicator class and override the method doHealthCheck. It might be nice to have a health indicator that can check if a URL is reachable. For example if we need to access a REST API reachable through HTTP in our application we can check if it is available.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package healthcheck
 
import org.springframework.boot.actuate.health.AbstractHealthIndicator
import org.springframework.boot.actuate.health.Health
 
class UrlHealthIndicator extends AbstractHealthIndicator {
 
    private final String url
 
    private final int timeout
 
    UrlHealthIndicator(final String url, final int timeout = 10 * 1000) {
        this.url = url
        this.timeout = timeout
    }
 
    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        final HttpURLConnection urlConnection =
                (HttpURLConnection) url.toURL().openConnection()
 
        final int responseCode =
                urlConnection.with {
                    requestMethod = 'HEAD'
                    readTimeout = timeout
                    connectTimeout = timeout
                    connect()
                    responseCode
                }
 
        // If code in 200 to 399 range everything is fine.
        responseCode in (200..399) ?
                builder.up() :
                builder.down(
                        new Exception(
                                "Invalid responseCode '${responseCode}' checking '${url}'."))
    }
}

In our Application class we create a Spring bean for this health indicator so it is picked up by the Spring Boot Actuator code:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package healthcheck
 
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.boot.actuate.health.DataSourceHealthIndicator
import org.springframework.boot.actuate.health.DiskSpaceHealthIndicatorProperties
 
class Application extends GrailsAutoConfiguration {
 
    static void main(String[] args) {
        GrailsApp.run(Application)
    }
 
    @Override
    Closure doWithSpring() {
        { ->
            // Create instance for URL health indicator.
            urlHealthCheck(UrlHealthIndicator, 'http://intranet', 2000)
 
            databaseHealthCheck(DataSourceHealthIndicator, dataSource)
 
            diskSpaceHealthIndicatorProperties(DiskSpaceHealthIndicatorProperties) {
                threshold = 250 * 1024 * 1024
            }
        }
    }
}

Now when we run our Grails application and access the /health endpoint we get the following JSON:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
{
    "status": "DOWN",
    "urlHealthCheck": {
        "status": "DOWN"
        "error": "java.net.UnknownHostException: intranet",
    },
    "databaseHealthCheck": {
        "status": "UP"
        "database": "H2",
        "hello": 1,
    },
    "diskSpace": {
        "status": "UP",
        "free": 96622411776,
        "threshold": 262144000
    },
}

Notice that the URL health check fails so the complete status is set to DOWN.

Written with Grails 3.0.1.

Reference: Grails Goodness: Adding Health Check Indicators from our JCG partner Hubert Ikkink at the JDriven blog.
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Hubert Ikkink

My name is Hubert A. Klein Ikkink also known as mrhaki. I work at the great IT company JDriven. Here I work on projects with Groovy & Grails, Gradle and Spring. At JDriven we focus on SpringSource technologies. All colleagues want to learn new technologies, support craftmanship and are very eager to learn. This is truly a great environment to work in.
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button