1818
1919= Helidon MP Health Check Guide
2020:h1Prefix: MP
21- :description: Helidon health- checks
22- :keywords: helidon, health- checks, health, check
21+ :description: Helidon health checks
22+ :keywords: helidon, health checks, health, check
2323:common-page-prefix-inc: ../../shared/common_prereqs/common_prereqs.adoc
2424
2525This guide describes how to create a sample MicroProfile (MP) project
@@ -77,17 +77,14 @@ curl http://localhost:8080/health
7777.JSON response:
7878----
7979{
80- "outcome": "UP",
8180 "status": "UP",
8281 "checks": [
8382 {
8483 "name": "deadlock",
85- "state": "UP",
8684 "status": "UP"
8785 },
8886 {
8987 "name": "diskSpace",
90- "state": "UP",
9188 "status": "UP",
9289 "data": {
9390 "free": "325.54 GB",
@@ -99,7 +96,6 @@ curl http://localhost:8080/health
9996 },
10097 {
10198 "name": "heapMemory",
102- "state": "UP",
10399 "status": "UP",
104100 "data": {
105101 "free": "230.87 MB",
@@ -115,10 +111,6 @@ curl http://localhost:8080/health
115111}
116112----
117113
118- NOTE: In MicroProfile Health 2.0 `outcome` and `state` were replaced by `status` in the JSON response wire format.
119- Helidon currently provides both fields for backwards compatibility, but use of `outcome` and `state` is deprecated
120- and will be removed in a future release. You should rely on `status` instead.
121-
122114=== Custom Liveness Health Checks
123115
124116You can create application-specific custom health checks and integrate them with Helidon
@@ -162,12 +154,10 @@ curl http://localhost:8080/health/live
162154.JSON response:
163155----
164156{
165- "outcome": "UP",
166157 "status": "UP",
167158 "checks": [
168159 {
169160 "name": "LivenessCheck",
170- "state": "UP",
171161 "status": "UP",
172162 "data": {
173163 "time": 1566338255331
@@ -177,7 +167,7 @@ curl http://localhost:8080/health/live
177167}
178168----
179169
180- === Custom Readiness Health Check
170+ === Custom Readiness Health Checks
181171
182172You can add a readiness check to indicate that the application is ready to be used. In this
183173example, the server will wait five seconds before it becomes ready.
@@ -201,20 +191,20 @@ import org.eclipse.microprofile.health.Readiness;
201191@Readiness // <2>
202192@ApplicationScoped
203193public class GreetReadinessCheck implements HealthCheck {
204- private AtomicLong readyTime = new AtomicLong(0);
194+ private final AtomicLong readyTime = new AtomicLong(0);
205195
206196
207197 @Override
208198 public HealthCheckResponse call() {
209199 return HealthCheckResponse.named("ReadinessCheck") // <3>
210- .state (isReady())
200+ .status (isReady())
211201 .withData("time", readyTime.get())
212202 .build();
213203 }
214204
215205 public void onStartUp(
216206 @Observes @Initialized(ApplicationScoped.class) Object init) {
217- readyTime = new AtomicLong (System.currentTimeMillis()); // <4>
207+ readyTime.set (System.currentTimeMillis()); // <4>
218208 }
219209
220210 /**
@@ -228,9 +218,9 @@ public class GreetReadinessCheck implements HealthCheck {
228218}
229219----
230220<1> Include additional imports.
231- <2> Annotation indicating that this is a readiness health- check.
221+ <2> Annotation indicating that this is a readiness health check.
232222<3> Build the `HealthCheckResponse` with status `UP` after five seconds, else `DOWN`.
233- <4> Initialize the time at startup.
223+ <4> Record the time at startup.
234224
235225
236226[source,bash]
@@ -246,12 +236,10 @@ curl -v http://localhost:8080/health/ready
246236< HTTP/1.1 503 Service Unavailable // <1>
247237...
248238{
249- "outcome": "DOWN",
250239 "status": "DOWN",
251240 "checks": [
252241 {
253242 "name": "ReadinessCheck",
254- "state": "DOWN",
255243 "status": "DOWN",
256244 "data": {
257245 "time": 1566399775700
@@ -275,12 +263,10 @@ curl -v http://localhost:8080/health/ready
275263< HTTP/1.1 200 OK // <1>
276264...
277265{
278- "outcome": "UP",
279266 "status": "UP",
280267 "checks": [
281268 {
282269 "name": "ReadinessCheck",
283- "state": "UP",
284270 "status": "UP",
285271 "data": {
286272 "time": 1566399775700
@@ -291,10 +277,121 @@ curl -v http://localhost:8080/health/ready
291277----
292278<1> The HTTP status is `200` indicating that the application is ready.
293279
280+ === Custom Startup Health Checks
281+
282+ 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.
283+ In this example, the server will wait eight seconds before it declares itself started.
284+
285+ [source,java]
286+ .Create a new `GreetStartedCheck` class with the following content:
287+ ----
288+
289+ package io.helidon.examples.quickstart.mp;
290+
291+ import java.time.Duration; // <1>
292+ import java.util.concurrent.atomic.AtomicLong;
293+ import jakarta.enterprise.context.ApplicationScoped;
294+
295+ import jakarta.enterprise.context.Initialized;
296+ import jakarta.enterprise.event.Observes;
297+ import org.eclipse.microprofile.health.HealthCheck;
298+ import org.eclipse.microprofile.health.HealthCheckResponse;
299+ import org.eclipse.microprofile.health.Started;
300+
301+ @Started // <2>
302+ @ApplicationScoped
303+ public class GreetStartedCheck implements HealthCheck {
304+ private final AtomicLong readyTime = new AtomicLong(0);
305+
306+
307+ @Override
308+ public HealthCheckResponse call() {
309+ return HealthCheckResponse.named("StartedCheck") // <3>
310+ .status(isStarted())
311+ .withData("time", readyTime.get())
312+ .build();
313+ }
314+
315+ public void onStartUp(
316+ @Observes @Initialized(ApplicationScoped.class) Object init) {
317+ readyTime.set(System.currentTimeMillis()); // <4>
318+ }
319+
320+ /**
321+ * Become ready after 5 seconds
322+ *
323+ * @return true if application ready
324+ */
325+ private boolean isStarted() {
326+ return Duration.ofMillis(System.currentTimeMillis() - readyTime.get()).getSeconds() >= 8;
327+ }
328+ }
329+ ----
330+ <1> Include additional imports.
331+ <2> Annotation indicating that this is a startup health check.
332+ <3> Build the `HealthCheckResponse` with status `UP` after eight seconds, else `DOWN`.
333+ <4> Record the time at startup of Helidon; the application will declare itself as started eight seconds later.
334+
335+
336+ [source,bash]
337+ .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:
338+ ----
339+ curl -v http://localhost:8080/health/started
340+ ----
341+
342+ [source,json]
343+ .HTTP response:
344+ ----
345+ ...
346+ < HTTP/1.1 503 Service Unavailable // <1>
347+ ...
348+ {
349+ "status": "DOWN",
350+ "checks": [
351+ {
352+ "name": "StartedCheck",
353+ "status": "DOWN",
354+ "data": {
355+ "time": 1566399775700
356+ }
357+ }
358+ ]
359+ }
360+ ----
361+ <1> The HTTP status is `503` since the application has not started.
362+
363+ [source,bash]
364+ .After eight seconds you will see the application has started:
365+ ----
366+ curl -v http://localhost:8080/health/started
367+ ----
368+
369+ [source,json]
370+ .JSON response:
371+ ----
372+ ...
373+ < HTTP/1.1 200 OK // <1>
374+ ...
375+ {
376+ "status": "UP",
377+ "checks": [
378+ {
379+ "name": "StartedCheck",
380+ "status": "UP",
381+ "data": {
382+ "time": 1566399775700
383+ }
384+ }
385+ ]
386+ }
387+ ----
388+ <1> The HTTP status is `200` indicating that the application is started.
389+
294390When using the health check URLs, you can get the following health check data:
295391
296- * custom liveness only - http://localhost:8080/health/live
297- * custom readiness only - http://localhost:8080/health/ready
392+ * liveness only - http://localhost:8080/health/live
393+ * readiness only - http://localhost:8080/health/ready
394+ * startup checks only - http://localhost:8080/health/started
298395* all health check data - http://localhost:8080/health
299396
300397[source,bash]
@@ -307,20 +404,24 @@ curl http://localhost:8080/health
307404.JSON response:
308405----
309406{
310- "outcome": "UP",
311407 "status": "UP",
312408 "checks": [
313409 {
314410 "name": "LivenessCheck",
315- "state": "UP",
316411 "status": "UP",
317412 "data": {
318413 "time": 1566403431536
319414 }
320415 },
321416 {
322417 "name": "ReadinessCheck",
323- "state": "UP",
418+ "status": "UP",
419+ "data": {
420+ "time": 1566403280639
421+ }
422+ },
423+ {
424+ "name": "StartedCheck",
324425 "status": "UP",
325426 "data": {
326427 "time": 1566403280639
@@ -384,6 +485,7 @@ health:
384485curl http://localhost:8080/myhealth
385486curl http://localhost:8080/myhealth/live
386487curl http://localhost:8080/myhealth/ready
488+ curl http://localhost:8080/myhealth/started
387489----
388490
389491The following example will change the root path and the health port.
@@ -414,12 +516,13 @@ health:
414516curl http://localhost:8081/myhealth
415517curl http://localhost:8081/myhealth/live
416518curl http://localhost:8081/myhealth/ready
519+ curl http://localhost:8081/myhealth/started
417520----
418521
419- === Using Liveness and Readiness Health Checks with Kubernetes
522+ === Using Liveness, Readiness, and Startup Health Checks with Kubernetes
420523
421524The following example shows how to integrate the Helidon health check API with an application that implements
422- health endpoints for the Kubernetes liveness and readiness probes.
525+ health endpoints for the Kubernetes liveness, readiness, and startup probes.
423526
424527*Delete the contents of `application.yaml` so that the default health endpoint path and port are used.*
425528
@@ -486,6 +589,14 @@ spec:
486589 initialDelaySeconds: 5 // <6>
487590 periodSeconds: 2
488591 timeoutSeconds: 3
592+ startupProbe:
593+ httpGet:
594+ path: /health/started // <7>
595+ port: 8080
596+ initialDelaySeconds: 8 // <8>
597+ periodSeconds: 10
598+ timeoutSeconds: 3
599+ failureThreshold: 3
489600---
490601----
491602<1> A service of type `NodePort` that serves the default routes on port `8080`.
@@ -494,6 +605,8 @@ spec:
494605<4> The liveness probe configuration.
495606<5> The HTTP endpoint for the readiness probe.
496607<6> The readiness probe configuration.
608+ <7> The HTTP endpoint for the startup probe.
609+ <8> The startup probe configuration.
497610
498611
499612[source,bash]
@@ -531,12 +644,12 @@ kubectl delete -f ./health.yaml
531644This guide demonstrated how to use health checks in a Helidon MP application as follows:
532645
533646* Access the default health checks
534- * Create and use custom readiness and liveness checks
647+ * Create and use custom readiness, liveness, and startup checks
535648* Customize the health check root path and port
536649* Integrate Helidon health check API with Kubernetes
537650
538651Refer to the following references for additional information:
539652
540- * MicroProfile health- check specification at https://github.com/eclipse/microprofile-health/releases/tag/2.0
541- * MicroProfile health- check Javadoc at https://javadoc.io/doc/org.eclipse.microprofile.health/microprofile-health-api/2.0
653+ * MicroProfile health check specification at https://github.com/eclipse/microprofile-health/releases/tag/2.0
654+ * MicroProfile health check Javadoc at https://javadoc.io/doc/org.eclipse.microprofile.health/microprofile-health-api/2.0
542655* Helidon Javadoc at https://helidon.io/docs/latest/apidocs/index.html?overview-summary.html
0 commit comments