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

3.x: Support built-in health check config at health.checks (retaining now-deprecated helidon.health for compatibility) #9337

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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.config.mp;

import java.util.Optional;
import java.util.logging.Logger;

import org.eclipse.microprofile.config.Config;

/**
* A utility class to handle MicroProfile configuration properties that should no longer be used.
* <p>
* For one major release, the property is retrieved through this class, to warn about the usage.
* In next major release, the deprecated property is removed (as is use of this class).
* <p>
* This class is closely patterned after {@code io.helidon.config.DeprecatedConfig} and works whether the MP config object
* is proxied by CDI or not. That other class can be used in conjunction with
* {@link io.helidon.config.mp.MpConfig#toHelidonConfig(org.eclipse.microprofile.config.Config)} for MP
* config objects that <em>are not</em> injected but that does work for MP config objects proxied by CDI. This one does work for
* those use cases.
*/
public final class DeprecatedMpConfig {
private static final Logger LOGGER = Logger.getLogger(DeprecatedMpConfig.class.getName());

private DeprecatedMpConfig() {
}

/**
* Get a value from config, attempting to read both the keys.
* Warning is logged if either the current key is not defined, or both the keys are defined.
*
* @param config configuration instance
* @param type type of the retrieved value
* @param currentKey key that should be used
* @param deprecatedKey key that should not be used
* @param <T> type of the retrieved value
* @return config value of the current key if exists, or the deprecated key if it does not, an empty {@code Optional}
* otherwise
*/
public static <T> Optional<T> getConfigValue(Config config, Class<T> type, String currentKey, String deprecatedKey) {
Optional<T> deprecatedConfig = config.getOptionalValue(deprecatedKey, type);
Optional<T> currentConfig = config.getOptionalValue(currentKey, type);

if (deprecatedConfig.isPresent()) {
if (currentConfig.isPresent()) {
LOGGER.warning("You are using both a deprecated configuration and a current one. "
+ "Deprecated key: \"" + deprecatedKey + "\", "
+ "current key: \"" + currentKey + "\", "
+ "only the current key will be used, and deprecated will be ignored.");
return currentConfig;
} else {
LOGGER.warning("You are using a deprecated configuration key. "
+ "Deprecated key: \"" + deprecatedKey + "\", "
+ "current key: \"" + currentKey + "\".");
return deprecatedConfig;
}
} else {
return currentConfig;
}
}
}
9 changes: 4 additions & 5 deletions docs/se/health.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
:rootdir: {docdir}/..

include::{rootdir}/includes/se.adoc[]
:built-in-health-check-config-prefix: health.checks

== Contents

Expand Down Expand Up @@ -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`
|=======

Expand Down
4 changes: 4 additions & 0 deletions health/health-checks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-mp</artifactId>
</dependency>
<dependency>
<!-- only needed for compilation, not required in runtime -->
<groupId>jakarta.enterprise</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@

package io.helidon.health.checks;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Formatter;
import java.util.Locale;
import java.util.function.Consumer;

import io.helidon.config.Config;
import io.helidon.config.mp.DeprecatedMpConfig;
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;
Expand All @@ -43,7 +43,8 @@
* <p>
* 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.
Expand All @@ -69,7 +70,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 = ".";
Expand All @@ -82,19 +83,34 @@ public class DiskSpaceHealthCheck implements HealthCheck {
static final String CONFIG_KEY_DISKSPACE_PREFIX = "diskSpace";

static final String CONFIG_KEY_PATH_SUFFIX = "path";
static final String CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX = "thresholdPercent";

/**
* Full configuration key for path, when configured through MicroProfile config.
*
* @deprecated The value will change to {@value CURRENT_CONFIG_KEY_PATH} in a future release
*/
public static final String CONFIG_KEY_PATH = HealthChecks.CONFIG_KEY_HEALTH_PREFIX
@Deprecated(since = "3.2.11")
public static final String CONFIG_KEY_PATH = HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX
+ "." + CONFIG_KEY_DISKSPACE_PREFIX
+ "." + CONFIG_KEY_PATH_SUFFIX;

static final String CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX = "thresholdPercent";
/**
* Full configuration key for threshold percent, when configured through Microprofile config.
*
* @deprecated The value will change to {@value CURRENT_CONFIG_KEY_THRESHOLD_PERCENT} in future release
*/
public static final String CONFIG_KEY_THRESHOLD_PERCENT = HealthChecks.CONFIG_KEY_HEALTH_PREFIX
@Deprecated(since = "3.2.11")
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;

Expand All @@ -114,16 +130,8 @@ 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
) {
try {
this.fileStore = Files.getFileStore(path.toPath());
} catch (IOException e) {
throw new HealthCheckException("Failed to obtain file store for path " + path.getAbsolutePath(), e);
}
this.thresholdPercent = thresholdPercent;
DiskSpaceHealthCheck(org.eclipse.microprofile.config.Config mpConfig) {
this(builder().update(applyConfig(mpConfig)));
}

private DiskSpaceHealthCheck(Builder builder) {
Expand Down Expand Up @@ -174,6 +182,29 @@ public static DiskSpaceHealthCheck create() {
return builder().build();
}

private static Consumer<Builder> applyConfig(org.eclipse.microprofile.config.Config mpConfig) {
return builder -> {
DeprecatedMpConfig.getConfigValue(mpConfig,
Path.class,
configKey(HealthChecks.CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX,
CONFIG_KEY_PATH_SUFFIX),
configKey(HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX,
CONFIG_KEY_PATH_SUFFIX))
.ifPresent(builder::path);
DeprecatedMpConfig.getConfigValue(mpConfig,
Double.class,
configKey(HealthChecks.CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX,
CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX),
configKey(HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX,
CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX))
.ifPresent(builder::thresholdPercent);
};
}

private static String configKey(String prefix, String suffix) {
return prefix + "." + CONFIG_KEY_DISKSPACE_PREFIX + "." + suffix;
}

@Override
public HealthCheckResponse call() {
long diskFreeInBytes;
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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() {
}
Expand Down Expand Up @@ -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...)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@
import java.util.Formatter;
import java.util.Locale;

import io.helidon.config.Config;
import io.helidon.config.mp.DeprecatedMpConfig;
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;
Expand All @@ -36,7 +35,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%.
* </p>
* <p>
Expand All @@ -62,8 +61,18 @@ public class HeapMemoryHealthCheck implements HealthCheck {

/**
* Config property key for heap memory threshold.
*
* @deprecated The value will change to {@value #CURRENT_CONFIG_KEY_THRESHOLD_PERCENT} in a future release
*/
public static final String CONFIG_KEY_THRESHOLD_PERCENT = HealthChecks.CONFIG_KEY_HEALTH_PREFIX
@Deprecated(since = "3.2.11")
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;

Expand All @@ -72,11 +81,18 @@ public class HeapMemoryHealthCheck implements HealthCheck {

// this will be ignored if not within CDI
@Inject
HeapMemoryHealthCheck(
Runtime runtime,
@ConfigProperty(name = CONFIG_KEY_THRESHOLD_PERCENT, defaultValue = "98") double threshold) {
this.thresholdPercent = threshold;
HeapMemoryHealthCheck(Runtime runtime, org.eclipse.microprofile.config.Config mpConfig) {
// Cannot use
this(runtime, DeprecatedMpConfig.getConfigValue(mpConfig,
Double.class,
thresholdPercentKey(HealthChecks.CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX),
thresholdPercentKey(HealthChecks.DEPRECATED_CONFIG_KEY_BUILT_IN_HEALTH_CHECKS_PREFIX))
.orElse(DEFAULT_THRESHOLD));
}

HeapMemoryHealthCheck(Runtime runtime, double thresholdPercent) {
this.rt = runtime;
this.thresholdPercent = thresholdPercent;
}

private HeapMemoryHealthCheck(Builder builder) {
Expand Down Expand Up @@ -104,6 +120,12 @@ public static HeapMemoryHealthCheck create() {
return builder().build();
}

private static String thresholdPercentKey(String prefix) {
return prefix + "."
+ CONFIG_KEY_HEAP_PREFIX + "."
+ CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX;
}

@Override
public HealthCheckResponse call() {
//Formatter ensures that returned delimiter will be always the same
Expand Down Expand Up @@ -174,7 +196,7 @@ public Builder thresholdPercent(double threshold) {
* @param config {@code Config} node for heap memory
* @return updated builder instance
*/
public Builder config(Config config) {
public Builder config(io.helidon.config.Config config) {
config.get(CONFIG_KEY_THRESHOLD_PERCENT_SUFFIX)
.asDouble()
.ifPresent(this::thresholdPercent);
Expand Down
3 changes: 2 additions & 1 deletion health/health-checks/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -26,6 +26,7 @@

requires io.helidon.common;
requires io.helidon.config;
requires io.helidon.config.mp;
requires io.helidon.health;
requires io.helidon.health.common;
requires static microprofile.config.api;
Expand Down
Loading
Loading