Health Groups

If you are reading this blog, you have probably already heard about Eclipse MicroProfile Health technology. In this article, we will introduce a new experimental extension to MicroProfile Health 2.2 called Health groups.

All of the source code that we will present in this article is available at this GitHub repository https://github.com/xstefank/health-groups.

MicroProfile 2.2 health checks

As you know, to define a health check procedure in MicroProfile Health you need something like this:

package io.xstefank;

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

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped // 1. CDI scope
@Readiness         // 2. Qualifier (Readiness, Liveness, Health)
public class ReadinessHealthCheck implements HealthCheck {   // 3. implements HealthCheck interface

    @Override
    public HealthCheckResponse call() {
        return HealthCheckResponse.up(ReadinessHealthCheck.class.getSimpleName());
    }
}

So just to recap, to define a health check your class:

  • needs to be a CDI bean

  • needs to have one of the health qualifiers (Readiness, Liveness, or deprecated Health)

  • must implement the HealthCheck interface

This is everything that you can use in MicroProfile 2.2. But what if you have a use case that doesn’t fall into one of Readiness or Liveness categories? The answer is custom health groups.

Health Groups

SmallRye Health 2.2.0 (already included in Quarkus 1.4.0) comes with a new addition to this API called health groups. A health group is basically a custom group of health check procedures that the user defines based on individual needs. As you probably noticed, Readiness and Liveness health checks already represent two predefined health groups. With the health groups feature you can define as many additional health check groups as you need.

Defining a health Group

To define a health group you need only to declare at least one health check procedure that belongs to the health group:

package io.xstefank;

import io.smallrye.health.HealthGroup;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
@HealthGroup("custom-group-1")
public class CustomGroup1Check implements HealthCheck {

    @Override
    public HealthCheckResponse call() {
        return HealthCheckResponse.up(CustomGroup1HC.class.getSimpleName());
    }
}

So the only difference now is the change of the qualifier for which we now use io.smallrye.health.HealthGroup. This qualifier takes a string argument representing the name of the health group. This is all that needs to be done to define a new custom health group and a health check procedure that belongs to it.

Accessing custom health groups

Accessing the custom health groups is done a similar manner to the original MicroProfile Health 2.2 health invocations. The URL to access a custom group is HOST:PORT/health/group/{group-name}. This will return all health check procedures belonging to the groups {group-name}. You can also find all health check procedures that belong to any of the custom defined health group by accessing HOST:PORT/health/group. Here is a summary of endpoints exposed in Quarkus 1.4.0:

Path Health checks

/health

@Readiness, @Liveness, @Health

/health/ready

@Readiness

/health/live

@Liveness

/health/group

all @HealthGroup(*)

/health/groups/group-name

@HealthGroup("group-name")

Combining different health groups

You are allowed to use more than one qualifier on any health check procedure that you define. For instance:

package io.xstefank;

import io.smallrye.health.HealthGroup;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Readiness;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
@HealthGroup("custom-group-1")
@HealthGroup("custom-group-2")
@Readiness
public class CustomGroup2ReadinessCheck implements HealthCheck {

    @Override
    public HealthCheckResponse call() {
        return HealthCheckResponse.up(CustomGroup2ReadinessCheck.class.getSimpleName());
    }
}

This procedure will now be available in custom-group-1, custom-group-2 and the readiness groups.

/health/group

{
    "checks": [
        {
            "name": "CustomGroup1Check",
            "status": "UP"
        },
        {
            "name": "CustomGroup2ReadinessCheck",
            "status": "UP"
        }
    ],
    "status": "UP"
}

/health/group/custom-group-1

{
    "checks": [
        {
            "name": "CustomGroup1Check",
            "status": "UP"
        },
        {
            "name": "CustomGroup2ReadinessCheck",
            "status": "UP"
        }
    ],
    "status": "UP"
}

/health/group/custom-group-2

{
    "checks": [
        {
            "name": "CustomGroup2ReadinessCheck",
            "status": "UP"
        }
    ],
    "status": "UP"
}

/health/ready

{
    "checks": [
        {
            "name": "CustomGroup2ReadinessCheck",
            "status": "UP"
        },
        {
            "name": "ReadinessHealthCheck",
            "status": "UP"
        }
    ],
    "status": "UP"
}

Where this can come particularly handy is if you want to reuse predefined readiness and liveness procedures for custom views or simplified processing. For example, if you have several liveness procedures one of which is not essential and takes a long time you may want to define a health group that will be excluding the expensive liveness health check computation.

Summary

We introduced the new experimental feature extending the MicroProfile Health 2.2 API called the Health Groups. This feature is available for use in the SmallRye Health 2.2.0 (Quarkus 1.4.0) and later releases. In Quarkus, the health Groups are already included in the smallrye-health extension. If you wish to use in a different container you need to add following dependencies:

<dependency>
  <groupId>io.smallrye</groupId>
  <artifactId>smallrye-health</artifactId>
  <version>${version.io.smallrye.health}</version>
</dependency>
<dependency>
  <groupId>io.smallrye</groupId>
  <artifactId>smallrye-health-extension-api</artifactId>
  <version>${version.io.smallrye.health}</version>
</dependency>

As we want to test features that we will eventually try to specify in MicroProfile, you can expect that if this feature will be used in Quarkus you will eventually see it in the MicroProfile Health specification. So if you are interested, please feel free to try it out, test it, and report any issues or enhancements in our issue tracker.