In the Ratpack core we can find the ratpack.health.HealthCheck
interface. We can implement this interface to check for example if a mail server, that we need in our application, is available. Any objects that implement this interface and are registered in the Guice registry are handled by Ratpack. Ratpack also offers a HealthCheckHandler
to output the results of all health checks or a single health check identified by a name. Instead of creating a new class that implements the HealthCheck
interface we can also use the HealtCheck.of
method. This method accepts an argument with the name of our check and a Closure
or lambda expression with the code that does the checking.
Let's write a sample Ratpack application using the Groovy DSL. We first use the HealthCheck.of
to implement a simple health check. We also using the HealthCheckHandler
so we can request information about the health check.
// File: src/ratpack/Ratpack.groovy import ratpack.exec.Promise import ratpack.health.HealthCheck import ratpack.health.HealthCheckHandler import ratpack.registry.Registry import static ratpack.groovy.Groovy.ratpack ratpack { bindings { // Add a simple HealtCheck implementation with // the of method. The name of our health check is // "application". We simply return a Promise with // a HealthCheck.Result value. If we get here we assume // the application is UP and running. add HealthCheck.of('application') { Registry registry -> Promise.value(HealthCheck.Result.healthy("UP")) } } handlers { // Assign HealthCheckHandler to health/ endpoint. // Optionally we can provide the name of the health check // to get the results specific for that health check. get('health/:name?', new HealthCheckHandler()) } }
When we run the application and request the URL http://localhost:5050/health
and http://localhost:5050/health/application
we get the following output:
$ http localhost:5050/health HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Expires: 0 Pragma: no-cache connection: keep-alive content-encoding: gzip content-type: text/plain;charset=UTF-8 transfer-encoding: chunked application : HEALTHY $ http localhost:5050/health/application HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Expires: 0 Pragma: no-cache connection: keep-alive content-encoding: gzip content-type: text/plain;charset=UTF-8 transfer-encoding: chunked application : HEALTHY
Now we create a new class that implements the HealthCheck
interface. We write a health check implementation that checks if the free space on a drive is less than a given threshold. If there is less space the health check should return an unhealthy status:
// File: src/main/groovy/com/mrhaki/ratpack/healthcheck/DiskSpaceHealthCheck.groovy package com.mrhaki.ratpack.healthcheck import groovy.transform.CompileStatic import ratpack.exec.Blocking import ratpack.exec.Promise import ratpack.health.HealthCheck import ratpack.registry.Registry import static org.apache.commons.io.FileUtils.byteCountToDisplaySize /** * Ratpack {@link HealthCheck} implementation to check for free space * on a disk. If the available free space is less than a given * threshold value than the check return unhealthy. */ @CompileStatic class DiskSpaceHealthCheck implements HealthCheck { /** * Default disk to check for free space is the local * disk our Ratpack app is running. */ File path = new File(".") /** * Default threshold is 50 MB. */ long threshold = 50L * 1024 * 1024 /** * Name for health check. Name must be unique * in Ratpack application. To add more instances * of this class use different names. */ String name = 'diskSpace' /** * Check available free space for the given {@link #path} value. Compare * this with the configured {@link #threshold} value. If available free * space is less than threshold return unhealthy result. * Otherwise return a healthy status. * * @param registry Ratpack registry. * @return Unhealthy result when available free space less than threshold, otherwise healthy. * @throws Exception Something goes wrong. */ @Override Promise<HealthCheck.Result> check(final Registry registry) throws Exception { Blocking.get { // Get available free space. Operation is potentially blocking // so inside a Blocking.get{} block. path.freeSpace }.map { Long diskFreeSpace -> // Format bytes to readable format with KB, MB, GB, etc. final String diskFreeSpaceFormatted = byteCountToDisplaySize(diskFreeSpace) final String thresholdFormatted = byteCountToDisplaySize(threshold) // Check if available free space is above given threshold. if (diskFreeSpace >= threshold) { // Everything is ok. HealthCheck.Result.healthy( 'Available: %s (threshold: %s)', diskFreeSpaceFormatted, thresholdFormatted) } else { // Available free space is below given threshold. // Create message with information // and signal as unhealthy. HealthCheck.Result.unhealthy( 'Free disk space below threshold. Available: %s (threshold: %s)', diskFreeSpaceFormatted, thresholdFormatted) } } } }
We only have to add this class to our registry and Ratpack will pick it up:
// File: src/ratpack/Ratpack.groovy import com.mrhaki.ratpack.healthcheck.DiskSpaceHealthCheck import ratpack.exec.Promise import ratpack.health.HealthCheck import ratpack.health.HealthCheckHandler import ratpack.registry.Registry import static ratpack.groovy.Groovy.ratpack ratpack { bindings { add new DiskSpaceHealthCheck(threshold: 50L * 1024 * 1024 * 1024 /* 50GB */) add HealthCheck.of('application') { Registry registry -> Promise.value(HealthCheck.Result.healthy("UP")) } } handlers { get('health/:name?', new HealthCheckHandler()) } }
We run the application and check the results of the health
endpoint:
$ http localhost:5050/health HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Expires: 0 Pragma: no-cache connection: keep-alive content-encoding: gzip content-type: text/plain;charset=UTF-8 transfer-encoding: chunked application : HEALTHY diskSpace : UNHEALTHY [Free disk space below threshold. Available: 41 GB (threshold: 50 GB)] $ http localhost:5050/health/diskSpace HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Expires: 0 Pragma: no-cache connection: keep-alive content-encoding: gzip content-type: text/plain;charset=UTF-8 transfer-encoding: chunked diskSpace : UNHEALTHY [Free disk space below threshold. Available: 41 GB (threshold: 50 GB)]
Written with Ratpack 1.1.1.