diff --git a/docs/se/health.adoc b/docs/se/health.adoc index 8c1b9257c8b..c1aa351eca5 100644 --- a/docs/se/health.adoc +++ b/docs/se/health.adoc @@ -23,6 +23,7 @@ :rootdir: {docdir}/.. include::{rootdir}/includes/se.adoc[] +:built-in-health-check-config-prefix: health.checks == Contents @@ -216,16 +217,14 @@ common health check statuses: |available disk space |`diskSpace` | link:{health-javadoc-base-url}/io/helidon/health/checks/DiskSpaceHealthCheck.html[`DiskSpaceHealthCheck`] -|`helidon.healthCheck.diskSpace.thresholdPercent` + -+ -`helidon.healthCheck.diskSpace.path` +|`{built-in-health-check-config-prefix}.diskSpace.thresholdPercent` + +`{built-in-health-check-config-prefix}.diskSpace.path` | `99.999` + -+ `/` |available heap memory | `heapMemory` | link:{health-javadoc-base-url}/io/helidon/health/checks/HeapMemoryHealthCheck.html[`HeapMemoryHealthCheck`] -|`helidon.healthCheck.heapMemory.thresholdPercent` +|`{built-in-health-check-config-prefix}.heapMemory.thresholdPercent` |`98` |======= diff --git a/health/health-checks/src/main/java/io/helidon/health/checks/DiskSpaceHealthCheck.java b/health/health-checks/src/main/java/io/helidon/health/checks/DiskSpaceHealthCheck.java index 7194c0521f2..5fc4ad0cee9 100644 --- a/health/health-checks/src/main/java/io/helidon/health/checks/DiskSpaceHealthCheck.java +++ b/health/health-checks/src/main/java/io/helidon/health/checks/DiskSpaceHealthCheck.java @@ -16,7 +16,6 @@ package io.helidon.health.checks; -import java.io.File; import java.io.IOException; import java.nio.file.FileStore; import java.nio.file.Files; @@ -26,12 +25,12 @@ import java.util.Locale; import io.helidon.config.Config; +import io.helidon.config.DeprecatedConfig; import io.helidon.health.HealthCheckException; import io.helidon.health.common.BuiltInHealthCheck; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; import org.eclipse.microprofile.health.Liveness; @@ -43,7 +42,8 @@ *
* By default, this health check has a threshold of 100%, meaning that it will never fail the threshold check. * Also, by default, it will check the root path {@code /}. These defaults can be modified using the - * {@value CONFIG_KEY_PATH} property (default {@value DEFAULT_PATH}), and the {@value CONFIG_KEY_THRESHOLD_PERCENT} + * {@value CURRENT_CONFIG_KEY_PATH} property (default {@value DEFAULT_PATH}), and the + * {@value CURRENT_CONFIG_KEY_THRESHOLD_PERCENT} * property (default {@value DEFAULT_THRESHOLD}, virtually 100). The threshold should be set to a percent, such as 50 for 50% or * 99 for 99%. If disk usage * exceeds this threshold, then the health check will fail. @@ -69,7 +69,7 @@ public class DiskSpaceHealthCheck implements HealthCheck { * directory as application path), use * {@link io.helidon.health.checks.DiskSpaceHealthCheck.Builder#path(java.nio.file.Path)}. * When running within a MicroProfile server, you can configure path using a configuration key - * {@value #CONFIG_KEY_PATH} + * {@value #CURRENT_CONFIG_KEY_PATH} * Defaults to {@value} */ public static final String DEFAULT_PATH = "."; @@ -87,14 +87,25 @@ public class DiskSpaceHealthCheck implements HealthCheck { /** * Full configuration key for path, when configured through MicroProfile config. */ - public static final String CONFIG_KEY_PATH = HealthChecks.CONFIG_KEY_HEALTH_PREFIX + public static final String CONFIG_KEY_PATH = HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX + "." + CONFIG_KEY_DISKSPACE_PREFIX + "." + CONFIG_KEY_PATH_SUFFIX; /** * Full configuration key for threshold percent, when configured through Microprofile config. */ - public static final String CONFIG_KEY_THRESHOLD_PERCENT = HealthChecks.CONFIG_KEY_HEALTH_PREFIX + public static final String CONFIG_KEY_THRESHOLD_PERCENT = HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX + + "." + CONFIG_KEY_DISKSPACE_PREFIX + + "." + CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX; + + // The following two constants are used in the Javadoc to nudge users toward using the config key prefix "health.checks" + // rather than the obsolete "helidon.health". Because the original public constants above have always referred to the + // now-deprecated config prefixes, those values are unchanged to preserve backward compatibility. + private static final String CURRENT_CONFIG_KEY_PATH = HealthChecks.CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX + + "." + CONFIG_KEY_DISKSPACE_PREFIX + + "." + CONFIG_KEY_PATH_SUFFIX; + + private static final String CURRENT_CONFIG_KEY_THRESHOLD_PERCENT = HealthChecks.CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX + "." + CONFIG_KEY_DISKSPACE_PREFIX + "." + CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX; @@ -114,16 +125,22 @@ public class DiskSpaceHealthCheck implements HealthCheck { } @Inject - DiskSpaceHealthCheck( - @ConfigProperty(name = CONFIG_KEY_PATH, defaultValue = DEFAULT_PATH) File path, - @ConfigProperty(name = CONFIG_KEY_THRESHOLD_PERCENT, defaultValue = "99.999") double thresholdPercent - ) { + DiskSpaceHealthCheck(Config rootConfig) { + Config diskSpaceConfig = DeprecatedConfig.get(rootConfig, + HealthChecks.CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX, + HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX) + .get(CONFIG_KEY_DISKSPACE_PREFIX); + Path path = diskSpaceConfig.get(CONFIG_KEY_PATH_SUFFIX) + .as(Path.class) + .orElse(Paths.get(".")); + thresholdPercent = diskSpaceConfig.get(CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX) + .asDouble() + .orElse(99.999d); try { - this.fileStore = Files.getFileStore(path.toPath()); + this.fileStore = Files.getFileStore(path); } catch (IOException e) { - throw new HealthCheckException("Failed to obtain file store for path " + path.getAbsolutePath(), e); + throw new HealthCheckException("Failed to obtain file store for path " + path, e); } - this.thresholdPercent = thresholdPercent; } private DiskSpaceHealthCheck(Builder builder) { diff --git a/health/health-checks/src/main/java/io/helidon/health/checks/HealthChecks.java b/health/health-checks/src/main/java/io/helidon/health/checks/HealthChecks.java index 87493c2fc14..d9e99bb9684 100644 --- a/health/health-checks/src/main/java/io/helidon/health/checks/HealthChecks.java +++ b/health/health-checks/src/main/java/io/helidon/health/checks/HealthChecks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021 Oracle and/or its affiliates. + * Copyright (c) 2018, 2024 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,8 @@ */ public final class HealthChecks { - static final String CONFIG_KEY_HEALTH_PREFIX = "helidon.health"; + static final String CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX = "health.checks"; + static final String DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX = "helidon.health"; private HealthChecks() { } @@ -114,9 +115,10 @@ public static HealthCheck[] healthChecks() { } /** - * Built-in health checks, set up using "helidon.health" configuration. + * Built-in health checks, set up using configuration at {@value CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX} or the deprecated + * {@value DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX}. * - * @param config configuration rooted at "helidon.health" + * @param config configuration at the node containing health checks config * @return built-in health checks, set up using the provided configuration * @see io.helidon.health.HealthSupport.Builder#addLiveness(org.eclipse.microprofile.health.HealthCheck...) */ diff --git a/health/health-checks/src/main/java/io/helidon/health/checks/HeapMemoryHealthCheck.java b/health/health-checks/src/main/java/io/helidon/health/checks/HeapMemoryHealthCheck.java index dedecaafa60..a9c155f6e3f 100644 --- a/health/health-checks/src/main/java/io/helidon/health/checks/HeapMemoryHealthCheck.java +++ b/health/health-checks/src/main/java/io/helidon/health/checks/HeapMemoryHealthCheck.java @@ -20,11 +20,11 @@ import java.util.Locale; import io.helidon.config.Config; +import io.helidon.config.DeprecatedConfig; import io.helidon.health.common.BuiltInHealthCheck; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; import org.eclipse.microprofile.health.Liveness; @@ -36,7 +36,7 @@ * By default, this health check has a threshold of {@value DEFAULT_THRESHOLD} ({@value DEFAULT_THRESHOLD}%). * If heap usage exceeds this level, then the server * is considered to be unhealthy. This default can be modified using the - * {@value CONFIG_KEY_THRESHOLD_PERCENT} property. The threshold should be set as a percent, such as + * {@value CURRENT_CONFIG_KEY_THRESHOLD_PERCENT} property. The threshold should be set as a percent, such as * 50 for 50% or 99 for 99%. *
*
@@ -63,10 +63,18 @@ public class HeapMemoryHealthCheck implements HealthCheck {
/**
* Config property key for heap memory threshold.
*/
- public static final String CONFIG_KEY_THRESHOLD_PERCENT = HealthChecks.CONFIG_KEY_HEALTH_PREFIX
+ public static final String CONFIG_KEY_THRESHOLD_PERCENT = HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX
+ "." + CONFIG_KEY_HEAP_PREFIX
+ "." + CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX;
+ // The following constant is used in the Javadoc to nudge users toward using the current config key prefix "health.checks"
+ // rather than the deprecated "helidon.health". The public constant above has always used the now-deprecated prefix so that
+ // value is unchanged to preserve backward compatibility.
+ private static final String CURRENT_CONFIG_KEY_THRESHOLD_PERCENT = HealthChecks.CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX
+ + "." + CONFIG_KEY_HEAP_PREFIX
+ + "." + CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX;
+
+
private final Runtime rt;
private final double thresholdPercent;
@@ -74,9 +82,19 @@ public class HeapMemoryHealthCheck implements HealthCheck {
@Inject
HeapMemoryHealthCheck(
Runtime runtime,
- @ConfigProperty(name = CONFIG_KEY_THRESHOLD_PERCENT, defaultValue = "98") double threshold) {
- this.thresholdPercent = threshold;
+ Config rootConfig) {
+ this(runtime, DeprecatedConfig.get(rootConfig,
+ HealthChecks.CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX,
+ HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX)
+ .get(CONFIG_KEY_HEAP_PREFIX)
+ .get(CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX)
+ .asDouble()
+ .orElse(98d));
+ }
+
+ HeapMemoryHealthCheck(Runtime runtime, double thresholdPercent) {
this.rt = runtime;
+ this.thresholdPercent = thresholdPercent;
}
private HeapMemoryHealthCheck(Builder builder) {
diff --git a/health/health-checks/src/test/java/io/helidon/health/checks/ConfigTest.java b/health/health-checks/src/test/java/io/helidon/health/checks/ConfigTest.java
index ff7d1054ced..39015adb15c 100644
--- a/health/health-checks/src/test/java/io/helidon/health/checks/ConfigTest.java
+++ b/health/health-checks/src/test/java/io/helidon/health/checks/ConfigTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
import io.helidon.common.http.MediaType;
import io.helidon.config.Config;
import io.helidon.config.ConfigSources;
+import io.helidon.config.DeprecatedConfig;
import io.helidon.health.HealthSupport;
import io.helidon.media.jsonp.JsonpSupport;
import io.helidon.webclient.WebClient;
@@ -69,7 +70,7 @@ static void shutdownServer(WebServer server) {
@Test
void bothFail() throws InterruptedException, ExecutionException, TimeoutException {
- JsonObject health = runWithConfig("bothFail", Http.Status.SERVICE_UNAVAILABLE_503.code());
+ JsonObject health = runWithConfig("bothFailWithDeprecatedPrefix.helidon.health", Http.Status.SERVICE_UNAVAILABLE_503.code());
JsonObject diskSpace = getLivenessCheck(health, "diskSpace");
assertThat("Disk space liveness return data", diskSpace, is(notNullValue()));
@@ -83,7 +84,7 @@ void bothFail() throws InterruptedException, ExecutionException, TimeoutExceptio
@Test
void bothPass() throws InterruptedException, ExecutionException, TimeoutException {
- JsonObject health = runWithConfig("bothPass", Http.Status.OK_200.code());
+ JsonObject health = runWithConfig("bothPassWithDeprecatedPrefix.helidon.health", Http.Status.OK_200.code());
JsonObject diskSpace = getLivenessCheck(health, "diskSpace");
assertThat("Disk space liveness return data", diskSpace, is(notNullValue()));
@@ -95,10 +96,25 @@ void bothPass() throws InterruptedException, ExecutionException, TimeoutExceptio
assertThat("Heap memory liveness check status", heapMemory.getString("status"), is("UP"));
}
+ @Test
+ void testWithoutHelidonPrefix() throws ExecutionException, InterruptedException, TimeoutException {
+ JsonObject health = runWithConfig("bothFailWithoutDeprecatedHelidonPrefix.health.checks",
+ Http.Status.SERVICE_UNAVAILABLE_503.code());
+ JsonObject diskSpace = getLivenessCheck(health, "diskSpace");
+
+ assertThat("Disk space liveness return data", diskSpace, is(notNullValue()));
+ assertThat("Disk space liveness check status", diskSpace.getString("status"), is("DOWN"));
+
+ JsonObject heapMemory = getLivenessCheck(health, "heapMemory");
+
+ assertThat("Heap memory liveness return data", heapMemory, is(notNullValue()));
+ assertThat("Heap memory liveness check status", heapMemory.getString("status"), is("DOWN"));
+ }
+
private JsonObject runWithConfig(String configKey, int expectedStatus) throws InterruptedException, ExecutionException,
TimeoutException {
HealthSupport healthSupport = HealthSupport.builder()
- .addLiveness(HealthChecks.healthChecks(testConfig.get(configKey + ".helidon.health")))
+ .addLiveness(HealthChecks.healthChecks(testConfig.get(configKey)))
.build();
WebServer webServer = null;
try {
diff --git a/health/health-checks/src/test/resources/testConfig.yaml b/health/health-checks/src/test/resources/testConfig.yaml
index b32513a91d4..46847147070 100644
--- a/health/health-checks/src/test/resources/testConfig.yaml
+++ b/health/health-checks/src/test/resources/testConfig.yaml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2024 Oracle and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,17 +13,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-bothFail:
+bothFailWithDeprecatedPrefix:
helidon:
health:
diskSpace:
thresholdPercent: 0.0
heapMemory:
thresholdPercent: 0.0
-bothPass:
+bothPassWithDeprecatedPrefix:
helidon:
health:
diskSpace:
thresholdPercent: 98.1
heapMemory:
- thresholdPercent: 98.1
\ No newline at end of file
+ thresholdPercent: 98.1
+# Following are set to zero to avoid the defaults and force a DOWN state the test can easily detect.
+bothFailWithoutDeprecatedHelidonPrefix:
+ health:
+ checks:
+ diskSpace:
+ thresholdPercent: 0.0
+ heapMemory:
+ thresholdPercent: 0.0
\ No newline at end of file
diff --git a/microprofile/health/pom.xml b/microprofile/health/pom.xml
index 198e85c53ea..e3355347e1b 100644
--- a/microprofile/health/pom.xml
+++ b/microprofile/health/pom.xml
@@ -60,6 +60,11 @@
+ * We specify 0 values to force the statuses to DOWN. The default config settings cause the checks to return UP, so if we
+ * detect DOWN statuses we know the config has been found and applied correctly.
+ */
+@HelidonTest
+@AddConfig(key = "health.checks.diskSpace.thresholdPercent", value = "0.0")
+@AddConfig(key = "health.checks.heapMemory.thresholdPercent", value = "0.0")
+class TestConfigPrefix {
+
+ @Inject
+ private WebTarget webTarget;
+
+ @Test
+ void testConfig() {
+ TestUtils.checkForFailure(webTarget);
+ }
+}
diff --git a/microprofile/health/src/test/java/io/helidon/microprofile/health/TestDeprecatedConfigPrefix.java b/microprofile/health/src/test/java/io/helidon/microprofile/health/TestDeprecatedConfigPrefix.java
new file mode 100644
index 00000000000..9ca5d09a0d3
--- /dev/null
+++ b/microprofile/health/src/test/java/io/helidon/microprofile/health/TestDeprecatedConfigPrefix.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.helidon.microprofile.health;
+
+import io.helidon.microprofile.tests.junit5.AddConfig;
+import io.helidon.microprofile.tests.junit5.HelidonTest;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.client.WebTarget;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests the deprecated config prefix.
+ *
+ * We specify 0 values to force the statuses to DOWN. The default config settings cause the checks to return UP, so if we
+ * detect DOWN statuses we know the config has been found and applied correctly.
+ */
+@HelidonTest
+@AddConfig(key = "helidon.health.diskSpace.thresholdPercent", value = "0.0")
+@AddConfig(key = "helidon.health.heapMemory.thresholdPercent", value = "0.0")
+class TestDeprecatedConfigPrefix {
+
+ @Inject
+ private WebTarget webTarget;
+
+ @Test
+ void testConfig() {
+ TestUtils.checkForFailure(webTarget);
+ }
+}
diff --git a/microprofile/health/src/test/java/io/helidon/microprofile/health/TestUtils.java b/microprofile/health/src/test/java/io/helidon/microprofile/health/TestUtils.java
new file mode 100644
index 00000000000..f46976a335c
--- /dev/null
+++ b/microprofile/health/src/test/java/io/helidon/microprofile/health/TestUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.helidon.microprofile.health;
+
+import io.helidon.common.http.Http;
+
+import jakarta.json.JsonObject;
+import jakarta.json.JsonValue;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+class TestUtils {
+ static JsonObject getLivenessCheck(JsonObject health, String checkName) {
+ return health.getJsonArray("checks").stream()
+ .map(JsonValue::asJsonObject)
+ .filter(jo -> jo.getString("name").equals(checkName))
+ .findFirst()
+ .orElse(null);
+ }
+
+ static void checkForFailure(WebTarget webTarget) {
+ Response response = webTarget.path("/health")
+ .request()
+ .get();
+
+ assertThat("Health endpoint status", response.getStatus(), is(Http.Status.SERVICE_UNAVAILABLE_503.code()));
+
+ JsonObject healthJson = response.readEntity(JsonObject.class);
+ JsonObject diskSpace = TestUtils.getLivenessCheck(healthJson, "diskSpace");
+ JsonObject heapMemory = TestUtils.getLivenessCheck(healthJson, "heapMemory");
+ assertThat("Disk space liveness return data", diskSpace, is(notNullValue()));
+ assertThat("Disk space liveness check status", diskSpace.getString("status"), is("DOWN"));
+ assertThat("Heap memory liveness return data", heapMemory, is(notNullValue()));
+ assertThat("Heap memory liveness check status", heapMemory.getString("status"), is("DOWN"));
+ }
+}