Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Health 4.0 #3707

Merged
merged 15 commits into from
Dec 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 145 additions & 32 deletions docs/mp/guides/04_health.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

= Helidon MP Health Check Guide
:h1Prefix: MP
:description: Helidon health-checks
:keywords: helidon, health-checks, health, check
:description: Helidon health checks
:keywords: helidon, health checks, health, check
:common-page-prefix-inc: ../../shared/common_prereqs/common_prereqs.adoc

This guide describes how to create a sample MicroProfile (MP) project
Expand Down Expand Up @@ -77,17 +77,14 @@ curl http://localhost:8080/health
.JSON response:
----
{
"outcome": "UP",
"status": "UP",
"checks": [
{
"name": "deadlock",
"state": "UP",
"status": "UP"
},
{
"name": "diskSpace",
"state": "UP",
"status": "UP",
"data": {
"free": "325.54 GB",
Expand All @@ -99,7 +96,6 @@ curl http://localhost:8080/health
},
{
"name": "heapMemory",
"state": "UP",
"status": "UP",
"data": {
"free": "230.87 MB",
Expand All @@ -115,10 +111,6 @@ curl http://localhost:8080/health
}
----

NOTE: In MicroProfile Health 2.0 `outcome` and `state` were replaced by `status` in the JSON response wire format.
Helidon currently provides both fields for backwards compatibility, but use of `outcome` and `state` is deprecated
and will be removed in a future release. You should rely on `status` instead.

=== Custom Liveness Health Checks

You can create application-specific custom health checks and integrate them with Helidon
Expand Down Expand Up @@ -162,12 +154,10 @@ curl http://localhost:8080/health/live
.JSON response:
----
{
"outcome": "UP",
"status": "UP",
"checks": [
{
"name": "LivenessCheck",
"state": "UP",
"status": "UP",
"data": {
"time": 1566338255331
Expand All @@ -177,7 +167,7 @@ curl http://localhost:8080/health/live
}
----

=== Custom Readiness Health Check
=== Custom Readiness Health Checks

You can add a readiness check to indicate that the application is ready to be used. In this
example, the server will wait five seconds before it becomes ready.
Expand All @@ -201,20 +191,20 @@ import org.eclipse.microprofile.health.Readiness;
@Readiness // <2>
@ApplicationScoped
public class GreetReadinessCheck implements HealthCheck {
private AtomicLong readyTime = new AtomicLong(0);
private final AtomicLong readyTime = new AtomicLong(0);


@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("ReadinessCheck") // <3>
.state(isReady())
.status(isReady())
.withData("time", readyTime.get())
.build();
}

public void onStartUp(
@Observes @Initialized(ApplicationScoped.class) Object init) {
readyTime = new AtomicLong(System.currentTimeMillis()); // <4>
readyTime.set(System.currentTimeMillis()); // <4>
}

/**
Expand All @@ -228,9 +218,9 @@ public class GreetReadinessCheck implements HealthCheck {
}
----
<1> Include additional imports.
<2> Annotation indicating that this is a readiness health-check.
<2> Annotation indicating that this is a readiness health check.
<3> Build the `HealthCheckResponse` with status `UP` after five seconds, else `DOWN`.
<4> Initialize the time at startup.
<4> Record the time at startup.


[source,bash]
Expand All @@ -246,12 +236,10 @@ curl -v http://localhost:8080/health/ready
< HTTP/1.1 503 Service Unavailable // <1>
...
{
"outcome": "DOWN",
"status": "DOWN",
"checks": [
{
"name": "ReadinessCheck",
"state": "DOWN",
"status": "DOWN",
"data": {
"time": 1566399775700
Expand All @@ -275,12 +263,10 @@ curl -v http://localhost:8080/health/ready
< HTTP/1.1 200 OK // <1>
...
{
"outcome": "UP",
"status": "UP",
"checks": [
{
"name": "ReadinessCheck",
"state": "UP",
"status": "UP",
"data": {
"time": 1566399775700
Expand All @@ -291,10 +277,121 @@ curl -v http://localhost:8080/health/ready
----
<1> The HTTP status is `200` indicating that the application is ready.

=== Custom Startup Health Checks

You can add a startup check to indicate whether or not the application has initialized to the point that the other health checks make sense.
In this example, the server will wait eight seconds before it declares itself started.

[source,java]
.Create a new `GreetStartedCheck` class with the following content:
----

package io.helidon.examples.quickstart.mp;

import java.time.Duration; // <1>
import java.util.concurrent.atomic.AtomicLong;
import jakarta.enterprise.context.ApplicationScoped;

import jakarta.enterprise.context.Initialized;
import jakarta.enterprise.event.Observes;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Started;

@Started // <2>
@ApplicationScoped
public class GreetStartedCheck implements HealthCheck {
private final AtomicLong readyTime = new AtomicLong(0);


@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("StartedCheck") // <3>
.status(isStarted())
.withData("time", readyTime.get())
.build();
}

public void onStartUp(
@Observes @Initialized(ApplicationScoped.class) Object init) {
readyTime.set(System.currentTimeMillis()); // <4>
}

/**
* Become ready after 5 seconds
*
* @return true if application ready
*/
private boolean isStarted() {
return Duration.ofMillis(System.currentTimeMillis() - readyTime.get()).getSeconds() >= 8;
}
}
----
<1> Include additional imports.
<2> Annotation indicating that this is a startup health check.
<3> Build the `HealthCheckResponse` with status `UP` after eight seconds, else `DOWN`.
<4> Record the time at startup of Helidon; the application will declare itself as started eight seconds later.


[source,bash]
.Build and run the application. Issue the curl command with -v within five seconds and you will see that the application has not yet started:
----
curl -v http://localhost:8080/health/started
----

[source,json]
.HTTP response:
----
...
< HTTP/1.1 503 Service Unavailable // <1>
...
{
"status": "DOWN",
"checks": [
{
"name": "StartedCheck",
"status": "DOWN",
"data": {
"time": 1566399775700
}
}
]
}
----
<1> The HTTP status is `503` since the application has not started.

[source,bash]
.After eight seconds you will see the application has started:
----
curl -v http://localhost:8080/health/started
----

[source,json]
.JSON response:
----
...
< HTTP/1.1 200 OK // <1>
...
{
"status": "UP",
"checks": [
{
"name": "StartedCheck",
"status": "UP",
"data": {
"time": 1566399775700
}
}
]
}
----
<1> The HTTP status is `200` indicating that the application is started.

When using the health check URLs, you can get the following health check data:

* custom liveness only - http://localhost:8080/health/live
* custom readiness only - http://localhost:8080/health/ready
* liveness only - http://localhost:8080/health/live
* readiness only - http://localhost:8080/health/ready
* startup checks only - http://localhost:8080/health/started
* all health check data - http://localhost:8080/health

[source,bash]
Expand All @@ -307,20 +404,24 @@ curl http://localhost:8080/health
.JSON response:
----
{
"outcome": "UP",
"status": "UP",
"checks": [
{
"name": "LivenessCheck",
"state": "UP",
"status": "UP",
"data": {
"time": 1566403431536
}
},
{
"name": "ReadinessCheck",
"state": "UP",
"status": "UP",
"data": {
"time": 1566403280639
}
},
{
"name": "StartedCheck",
"status": "UP",
"data": {
"time": 1566403280639
Expand Down Expand Up @@ -384,6 +485,7 @@ health:
curl http://localhost:8080/myhealth
curl http://localhost:8080/myhealth/live
curl http://localhost:8080/myhealth/ready
curl http://localhost:8080/myhealth/started
----

The following example will change the root path and the health port.
Expand Down Expand Up @@ -414,12 +516,13 @@ health:
curl http://localhost:8081/myhealth
curl http://localhost:8081/myhealth/live
curl http://localhost:8081/myhealth/ready
curl http://localhost:8081/myhealth/started
----

=== Using Liveness and Readiness Health Checks with Kubernetes
=== Using Liveness, Readiness, and Startup Health Checks with Kubernetes

The following example shows how to integrate the Helidon health check API with an application that implements
health endpoints for the Kubernetes liveness and readiness probes.
health endpoints for the Kubernetes liveness, readiness, and startup probes.

*Delete the contents of `application.yaml` so that the default health endpoint path and port are used.*

Expand Down Expand Up @@ -486,6 +589,14 @@ spec:
initialDelaySeconds: 5 // <6>
periodSeconds: 2
timeoutSeconds: 3
startupProbe:
httpGet:
path: /health/started // <7>
port: 8080
initialDelaySeconds: 8 // <8>
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
---
----
<1> A service of type `NodePort` that serves the default routes on port `8080`.
Expand All @@ -494,6 +605,8 @@ spec:
<4> The liveness probe configuration.
<5> The HTTP endpoint for the readiness probe.
<6> The readiness probe configuration.
<7> The HTTP endpoint for the startup probe.
<8> The startup probe configuration.


[source,bash]
Expand Down Expand Up @@ -531,12 +644,12 @@ kubectl delete -f ./health.yaml
This guide demonstrated how to use health checks in a Helidon MP application as follows:

* Access the default health checks
* Create and use custom readiness and liveness checks
* Create and use custom readiness, liveness, and startup checks
* Customize the health check root path and port
* Integrate Helidon health check API with Kubernetes

Refer to the following references for additional information:

* MicroProfile health-check specification at https://github.com/eclipse/microprofile-health/releases/tag/2.0
* MicroProfile health-check Javadoc at https://javadoc.io/doc/org.eclipse.microprofile.health/microprofile-health-api/2.0
* MicroProfile health check specification at https://github.com/eclipse/microprofile-health/releases/tag/2.0
* MicroProfile health check Javadoc at https://javadoc.io/doc/org.eclipse.microprofile.health/microprofile-health-api/2.0
* Helidon Javadoc at https://helidon.io/docs/latest/apidocs/index.html?overview-summary.html
Loading