Health Check

Health Checks are important in platforms like Kubernetes because it allows the infrastructure to be aware of the state of the application.

There are two different types of health checks:

  • Liveness probes tell your platform if your application is running ok or not. When your liveness probe is down, your platform might restart your instance to guarantee that you have the minimum required amount of running instances in production.

  • Readiness probes tell your platform if your application is warm enough to reply to requests in a reasonable amount of time. Java applications, for example, might need some time to warm up, so the readiness probe should be up only when it’s ready to reply to a request in a timely manner. Checks that depend on other services should be implemented as readiness probes: if a remote service is down, restarting your application won’t fix the issue.

Add the Health extension

Just open a new terminal window, and make sure you’re at the root of your tutorial-app project, then run:

  • Maven

  • Quarkus CLI

./mvnw quarkus:add-extension -D"extension=quarkus-smallrye-health"
quarkus extension add quarkus-smallrye-health

Invoke the /health endpoint

Just by adding the Health extension you’ll have a /q/health endpoint providing a very trivial health check.

Run the following command:

curl localhost:8080/q/health
{
    "status": "UP",
    "checks": [
        {
            "name": "Database connections health check",
            "status": "UP"
        }
    ]
}

Notice that since we’re using the Hibernate and database extensions, Quarkus automatically added a readiness probe checking the status of our database connections.

You can modify the default path by adding the following property in applications.properties :
quarkus.smallrye-health.root-path=/health

Add a custom liveness probe

Create a new LivenessProbe Java class in src/main/java in the com.redhat.developers package with the following contents:

package com.redhat.developers;

import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Liveness;

@Liveness
public class LivenessProbe implements HealthCheck {
    @Override
    public HealthCheckResponse call() {
        return HealthCheckResponse.up("I'm alive");
    }

}

Add a custom readiness probe

In dev mode, all your health checks are visible in health UI: http://localhost:8080/q/health-ui/.

Some extensions may provide default health checks, including that the extension will automatically register its health checks. For example, quarkus-agroal (that is used to manage Quarkus datasources) automatically registers a readiness health check that will validate each datasource.

Since the readiness of the database is already assessed just by adding those extensions, we should look into defining health checks for other dependencies that we have. As we depend on the availability of https://fruityvice.com, let’s create a new ReadinessProbe to assess its availability prior to using it.

We will define a new Java class in src/main/java in the com.redhat.developers package with the following contents:

package com.redhat.developers;

import io.smallrye.health.checks.UrlHealthCheck;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.Readiness;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.HttpMethod;

@ApplicationScoped
public class CustomHealthCheck {

    @ConfigProperty(name = "com.redhat.developers.FruityViceService/mp-rest/url")
    String externalURL;

    @Readiness (1)
    HealthCheck checkURL() {
        return new UrlHealthCheck(externalURL+"/api/fruit/banana") (2)
                .name("ExternalURL health check").requestMethod(HttpMethod.GET).statusCode(200);
    }

}
1 Annotate the method with org.eclipse.microprofile.health.Readiness to signal its implementation.
2 UrlHealthCheck checks if host is reachable using a Http URL connection.

Invoke the /health endpoint with custom probes

Run the following command:

curl localhost:8080/health
{
    "status": "UP",
    "checks": [
        {
            "name": "I'm alive",
            "status": "UP"
        },
        {
            "name": "ExternalURL health check",
            "status": "UP",
            "data": {
                "host": "GET https://fruityvice.com/api/fruit/banana"
            }
        },
        {
            "name": "Database connections health check",
            "status": "UP"
        }
    ]
}

You can see that the /health endpoint consolidates information from both the liveness and readiness probes.

Invoke the liveness endpoint

Run the following command:

curl localhost:8080/health/live
{
    "status": "UP",
    "checks": [
        {
            "name": "I'm alive",
            "status": "UP"
        }
    ]
}

You can see that the liveness endpoint only returns information about the liveness probes.

Invoke the readiness endpoint

Run the following command:

curl localhost:8080/health/ready
{
    "status": "UP",
    "checks": [
        {
            "name": "ExternalURL health check",
            "status": "UP",
            "data": {
                "host": "GET https://fruityvice.com/api/fruit/banana"
            }
        },
        {
            "name": "Database connections health check",
            "status": "UP"
        }
    ]
}

You can see that the readiness endpoint only returns information about the readiness probes.

The Health extension and Kubernetes

If you’re using the Quarkus Kubernetes extension, the liveness and readiness probes are automatically configured in your Deployment when you generate the Kubernetes yaml files.