From f08cb8bb0ef2ebcab51c2216a330a6dbcaa8590e Mon Sep 17 00:00:00 2001 From: Bue-von-hon Date: Tue, 14 Feb 2023 23:53:18 +0900 Subject: [PATCH 01/29] Added DefaultCpuHealthChecker Motivation: Resolves part of #1854 Some users may want to use CPU usage to determine if their instance is healthy. From now on, Users can perform health checks in the following ways ``` DefaultCpuHealthChecker cpuHealthChecker = new DefaultCpuHealthChecker(20.0); cpuHealthChecker.isHealthy(); ``` Modifications: - Added DefaultCpuHealthChecker that checks cpu-usage by OperatingSystemMXBean Result: A User can health-check with system-cpu-usage p.s. Implemented this by referencing ProcessorMetrics.java in the micrometer core. --- .../healthcheck/DefaultCpuHealthChecker.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java new file mode 100644 index 00000000000..f4dba0647d0 --- /dev/null +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -0,0 +1,74 @@ +package com.linecorp.armeria.server.healthcheck; + +import static java.util.Objects.requireNonNull; + +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +public class DefaultCpuHealthChecker implements HealthChecker{ + + private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = Arrays.asList( + "com.ibm.lang.management.OperatingSystemMXBean", // J9 + "com.sun.management.OperatingSystemMXBean" // HotSpot + ); + + private final OperatingSystemMXBean operatingSystemBean; + + private final Class operatingSystemBeanClass; + + private final Method systemCpuUsage; + + private final double targetCpuUsage; + + public DefaultCpuHealthChecker(final double targetCpuUsage) { + this.targetCpuUsage = targetCpuUsage; + this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); + this.operatingSystemBeanClass = getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES); + this.systemCpuUsage = detectMethod("getSystemCpuLoad"); + } + + @Override + public boolean isHealthy() { + double cpuUsage = invoke(systemCpuUsage); + return cpuUsage <= targetCpuUsage; + } + + private double invoke(final Method method) { + try { + return (double) method.invoke(operatingSystemBean); + } + catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + return Double.NaN; + } + } + + private Method detectMethod(final String name) { + requireNonNull(name); + if (operatingSystemBeanClass == null) { + return null; + } + try { + // ensure the Bean we have is actually an instance of the interface + requireNonNull(operatingSystemBeanClass.cast(operatingSystemBean)); + return operatingSystemBeanClass.getMethod(name); + } + catch (ClassCastException | NoSuchMethodException | SecurityException e) { + return null; + } + } + + private Class getFirstClassFound(final List classNames) { + for (String className : classNames) { + try { + return Class.forName(className); + } + catch (ClassNotFoundException ignore) { + } + } + return null; + } +} From 08c706ef800c2d4ab4483352dce64b229ab23492 Mon Sep 17 00:00:00 2001 From: Bue-von-hon Date: Wed, 1 Mar 2023 00:19:46 +0900 Subject: [PATCH 02/29] Fixed javadoc and lint based on code review Modifications: - Fixed DefaultCpuHealthChecker added copyright header, added javadocs, Change health check from range-based to ratio-based, added nullable annotations, added requireNonNull method for nullable method calls --- .../healthcheck/DefaultCpuHealthChecker.java | 65 ++++++++++++++----- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index f4dba0647d0..35e378a1ea0 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -1,3 +1,18 @@ +/* + * Copyright 2015 LINE Corporation + * + * LINE Corporation licenses this file to you 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: + * + * https://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 com.linecorp.armeria.server.healthcheck; import static java.util.Objects.requireNonNull; @@ -9,7 +24,12 @@ import java.util.Arrays; import java.util.List; -public class DefaultCpuHealthChecker implements HealthChecker{ +import com.linecorp.armeria.common.annotation.Nullable; + +/** + * Forked from ProcessorMetrics.java in the micrometer core + */ +public class DefaultCpuHealthChecker implements HealthChecker { private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = Arrays.asList( "com.ibm.lang.management.OperatingSystemMXBean", // J9 @@ -24,49 +44,62 @@ public class DefaultCpuHealthChecker implements HealthChecker{ private final double targetCpuUsage; - public DefaultCpuHealthChecker(final double targetCpuUsage) { - this.targetCpuUsage = targetCpuUsage; + private final Method processCpuUsage; + + private final double targetProcessCpuLoad; + + /** + * Instantiates a new Default cpu health checker. + * + * @param cpuUsage the cpu usage + * @param cpuIdle the cpu idle + * @param processCpuUsage the process cpu usage + * @param processCpuIdle the process cpu idle + */ + public DefaultCpuHealthChecker(final int cpuUsage, final int cpuIdle, + final int processCpuUsage, final int processCpuIdle) { + this.targetCpuUsage = (double) cpuUsage / cpuIdle; + this.targetProcessCpuLoad = (double) processCpuUsage / processCpuIdle; this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); - this.operatingSystemBeanClass = getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES); - this.systemCpuUsage = detectMethod("getSystemCpuLoad"); + this.operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); + this.systemCpuUsage = requireNonNull(detectMethod("getSystemCpuLoad")); + this.processCpuUsage = requireNonNull(detectMethod("getProcessCpuLoad")); } @Override public boolean isHealthy() { - double cpuUsage = invoke(systemCpuUsage); - return cpuUsage <= targetCpuUsage; + final double currentSystemCpuUsage = invoke(systemCpuUsage); + final double currentProcessCpuUsage = invoke(processCpuUsage); + return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; } private double invoke(final Method method) { try { return (double) method.invoke(operatingSystemBean); - } - catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { return Double.NaN; } } + @Nullable private Method detectMethod(final String name) { requireNonNull(name); - if (operatingSystemBeanClass == null) { - return null; - } try { // ensure the Bean we have is actually an instance of the interface requireNonNull(operatingSystemBeanClass.cast(operatingSystemBean)); return operatingSystemBeanClass.getMethod(name); - } - catch (ClassCastException | NoSuchMethodException | SecurityException e) { + } catch (ClassCastException | NoSuchMethodException | SecurityException e) { return null; } } + @Nullable private Class getFirstClassFound(final List classNames) { for (String className : classNames) { try { return Class.forName(className); - } - catch (ClassNotFoundException ignore) { + } catch (ClassNotFoundException ignore) { + } } return null; From 551263af9941498d227d1d80efb44d86892ed293 Mon Sep 17 00:00:00 2001 From: Bue-von-hon Date: Wed, 1 Mar 2023 09:46:56 +0900 Subject: [PATCH 03/29] Fix Lint added ending period into first sentence of Javadoc --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index 35e378a1ea0..e1c1b841c88 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -27,7 +27,7 @@ import com.linecorp.armeria.common.annotation.Nullable; /** - * Forked from ProcessorMetrics.java in the micrometer core + * Forked from ProcessorMetrics.java in the micrometer core. */ public class DefaultCpuHealthChecker implements HealthChecker { @@ -99,7 +99,6 @@ private Class getFirstClassFound(final List classNames) { try { return Class.forName(className); } catch (ClassNotFoundException ignore) { - } } return null; From afd1843a37766d525d2f46d4c6a84f232e064e6f Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Sat, 11 Mar 2023 14:58:48 +0900 Subject: [PATCH 04/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: jrhee17 --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index e1c1b841c88..7fbaa882f0c 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 LINE Corporation + * Copyright 2023 LINE Corporation * * LINE Corporation licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance From 5e5069e6c9651b8cf52f1e63de1dfa8cf4eb04fd Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:03:20 +0900 Subject: [PATCH 05/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: Ikhun Um --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index 7fbaa882f0c..db778afec75 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -31,7 +31,7 @@ */ public class DefaultCpuHealthChecker implements HealthChecker { - private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = Arrays.asList( + private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = ImmutableList.of( "com.ibm.lang.management.OperatingSystemMXBean", // J9 "com.sun.management.OperatingSystemMXBean" // HotSpot ); From e4132b4eae4c0cd2e639023050f20463062200bd Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:04:50 +0900 Subject: [PATCH 06/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: jrhee17 --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index db778afec75..bd4600d8d5b 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -40,10 +40,12 @@ public class DefaultCpuHealthChecker implements HealthChecker { private final Class operatingSystemBeanClass; + @Nullable private final Method systemCpuUsage; private final double targetCpuUsage; + @Nullable private final Method processCpuUsage; private final double targetProcessCpuLoad; From 35da7bc1d23308071bfdc1d4fdfbcac0a7a9efd1 Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:05:06 +0900 Subject: [PATCH 07/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: jrhee17 --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index bd4600d8d5b..393280b0d34 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -58,7 +58,7 @@ public class DefaultCpuHealthChecker implements HealthChecker { * @param processCpuUsage the process cpu usage * @param processCpuIdle the process cpu idle */ - public DefaultCpuHealthChecker(final int cpuUsage, final int cpuIdle, + public DefaultCpuHealthChecker(int cpuUsage, int cpuIdle, final int processCpuUsage, final int processCpuIdle) { this.targetCpuUsage = (double) cpuUsage / cpuIdle; this.targetProcessCpuLoad = (double) processCpuUsage / processCpuIdle; From a0c04bb3fbdede279d09bffaafa1c8f60bea192e Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:06:16 +0900 Subject: [PATCH 08/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: jrhee17 --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index 393280b0d34..d0b16fe3f3d 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -64,8 +64,8 @@ public DefaultCpuHealthChecker(int cpuUsage, int cpuIdle, this.targetProcessCpuLoad = (double) processCpuUsage / processCpuIdle; this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); this.operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); - this.systemCpuUsage = requireNonNull(detectMethod("getSystemCpuLoad")); - this.processCpuUsage = requireNonNull(detectMethod("getProcessCpuLoad")); + this.systemCpuUsage = detectMethod("getSystemCpuLoad"); + this.processCpuUsage = detectMethod("getProcessCpuLoad"); } @Override From dd68de92f7e2f51b2da3df0100cd05a15977d2ab Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:06:37 +0900 Subject: [PATCH 09/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: jrhee17 --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index d0b16fe3f3d..376ccb2f24c 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -96,7 +96,7 @@ private Method detectMethod(final String name) { } @Nullable - private Class getFirstClassFound(final List classNames) { + private static Class getFirstClassFound(final List classNames) { for (String className : classNames) { try { return Class.forName(className); From 893406657851d484514f5c091a3c0b4405a76ddb Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:07:25 +0900 Subject: [PATCH 10/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: Trustin Lee --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index 376ccb2f24c..013c55b3a61 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -99,7 +99,7 @@ private Method detectMethod(final String name) { private static Class getFirstClassFound(final List classNames) { for (String className : classNames) { try { - return Class.forName(className); + return Class.forName(className, false, getClass().getClassLoader()); } catch (ClassNotFoundException ignore) { } } From 32fd4f7a6183106a06da26ff0d93a802c6a0178a Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Sat, 11 Mar 2023 16:18:36 +0900 Subject: [PATCH 11/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: jrhee17 --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index 013c55b3a61..f3a12b8c540 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -85,7 +85,6 @@ private double invoke(final Method method) { @Nullable private Method detectMethod(final String name) { - requireNonNull(name); try { // ensure the Bean we have is actually an instance of the interface requireNonNull(operatingSystemBeanClass.cast(operatingSystemBean)); From 0a0f8151d5e9f9cd34962469365d5655879860f7 Mon Sep 17 00:00:00 2001 From: Bue-von-hon Date: Sat, 18 Mar 2023 20:57:38 +0900 Subject: [PATCH 12/29] Fixed javadoc, access modifier, invoke method's algorithm and Added Test class for cpuHealthChecker, factory method into HealthChecker Motivation: Apply readability and performance improvements suggested in code reviews. Added comment on public method. Added test for DefaultCpuHealthChecker. Modifications: - Fixed DefaultCpuHealthChecker#invoke method to use methodHandlers instead of reflection for better performance. - Fixed a complex constructor to be more readable. - Fixed the systemCpuUsage and processCpuUsage's access modifier for testing. - Added javadoc for public method in DefaultCpuHealthChecker. - Added Factory Method into HealthChecker. - Added test class for DefaultCpuHealthChecker. Result: better performing DefaultCpuHealthChecker and tests. --- .../healthcheck/DefaultCpuHealthChecker.java | 45 ++++++++++++------- .../server/healthcheck/HealthChecker.java | 4 ++ .../DefaultCpuHealthCheckerTest.java | 34 ++++++++++++++ 3 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 core/src/test/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthCheckerTest.java diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index f3a12b8c540..7b8abc86c5b 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -17,19 +17,26 @@ import static java.util.Objects.requireNonNull; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Arrays; import java.util.List; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; + import com.linecorp.armeria.common.annotation.Nullable; /** - * Forked from ProcessorMetrics.java in the micrometer core. + * The Default cpu health checker.
+ * Here's an example of how to use it.
+ * final DefaultCpuHealthChecker cpuHealthChecker = HealthChecker.of(10, 10);
+ * final boolean healthy = cpuHealthChecker.isHealthy(); */ -public class DefaultCpuHealthChecker implements HealthChecker { +// Forked from ProcessorMetrics.java in the micrometer core. +class DefaultCpuHealthChecker implements HealthChecker { private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = ImmutableList.of( "com.ibm.lang.management.OperatingSystemMXBean", // J9 @@ -41,33 +48,35 @@ public class DefaultCpuHealthChecker implements HealthChecker { private final Class operatingSystemBeanClass; @Nullable - private final Method systemCpuUsage; + @VisibleForTesting + final Method systemCpuUsage; private final double targetCpuUsage; @Nullable - private final Method processCpuUsage; + @VisibleForTesting + final Method processCpuUsage; private final double targetProcessCpuLoad; /** * Instantiates a new Default cpu health checker. * - * @param cpuUsage the cpu usage - * @param cpuIdle the cpu idle - * @param processCpuUsage the process cpu usage - * @param processCpuIdle the process cpu idle + * @param targetCpuUsage the target cpu usage + * @param targetProcessCpuLoad the target process cpu usage */ - public DefaultCpuHealthChecker(int cpuUsage, int cpuIdle, - final int processCpuUsage, final int processCpuIdle) { - this.targetCpuUsage = (double) cpuUsage / cpuIdle; - this.targetProcessCpuLoad = (double) processCpuUsage / processCpuIdle; + public DefaultCpuHealthChecker(int targetCpuUsage, int targetProcessCpuLoad) { + this.targetCpuUsage = targetCpuUsage; + this.targetProcessCpuLoad = targetProcessCpuLoad; this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); this.operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); this.systemCpuUsage = detectMethod("getSystemCpuLoad"); this.processCpuUsage = detectMethod("getProcessCpuLoad"); } + /** + * Returns true if and only if System CPU Usage and Processes cpu usage is below the target usage. + */ @Override public boolean isHealthy() { final double currentSystemCpuUsage = invoke(systemCpuUsage); @@ -77,8 +86,10 @@ public boolean isHealthy() { private double invoke(final Method method) { try { - return (double) method.invoke(operatingSystemBean); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + final MethodHandle mh = lookup.unreflect(method); + return (double) mh.invoke(operatingSystemBean); + } catch (Throwable e) { return Double.NaN; } } @@ -98,7 +109,7 @@ private Method detectMethod(final String name) { private static Class getFirstClassFound(final List classNames) { for (String className : classNames) { try { - return Class.forName(className, false, getClass().getClassLoader()); + return Class.forName(className, false, DefaultCpuHealthChecker.class.getClassLoader()); } catch (ClassNotFoundException ignore) { } } diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java index 17fa76e253f..d10b1a20439 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java @@ -88,6 +88,10 @@ static ListenableHealthChecker of(Supplier Date: Wed, 5 Apr 2023 20:55:46 +0900 Subject: [PATCH 13/29] Fix Lint, Construct method's access level Modification: - Move the static factory method to DefaultCpuHealthChecker. --- .../server/healthcheck/DefaultCpuHealthChecker.java | 8 ++++++-- .../armeria/server/healthcheck/HealthChecker.java | 4 ---- .../server/healthcheck/DefaultCpuHealthCheckerTest.java | 5 +++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index 7b8abc86c5b..6f7971ddc69 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -36,7 +36,7 @@ * final boolean healthy = cpuHealthChecker.isHealthy(); */ // Forked from ProcessorMetrics.java in the micrometer core. -class DefaultCpuHealthChecker implements HealthChecker { +final class DefaultCpuHealthChecker implements HealthChecker { private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = ImmutableList.of( "com.ibm.lang.management.OperatingSystemMXBean", // J9 @@ -65,7 +65,7 @@ class DefaultCpuHealthChecker implements HealthChecker { * @param targetCpuUsage the target cpu usage * @param targetProcessCpuLoad the target process cpu usage */ - public DefaultCpuHealthChecker(int targetCpuUsage, int targetProcessCpuLoad) { + private DefaultCpuHealthChecker(int targetCpuUsage, int targetProcessCpuLoad) { this.targetCpuUsage = targetCpuUsage; this.targetProcessCpuLoad = targetProcessCpuLoad; this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); @@ -74,6 +74,10 @@ public DefaultCpuHealthChecker(int targetCpuUsage, int targetProcessCpuLoad) { this.processCpuUsage = detectMethod("getProcessCpuLoad"); } + public static DefaultCpuHealthChecker of(int targetCpuUsage, int targetProcessCpuLoad) { + return new DefaultCpuHealthChecker(targetCpuUsage, targetProcessCpuLoad); + } + /** * Returns true if and only if System CPU Usage and Processes cpu usage is below the target usage. */ diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java index d10b1a20439..17fa76e253f 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java @@ -88,10 +88,6 @@ static ListenableHealthChecker of(Supplier Date: Thu, 8 Jun 2023 16:20:03 +0900 Subject: [PATCH 14/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java Co-authored-by: Trustin Lee --- .../armeria/server/healthcheck/DefaultCpuHealthChecker.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java index 6f7971ddc69..1abdb3961dd 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java @@ -30,10 +30,12 @@ import com.linecorp.armeria.common.annotation.Nullable; /** - * The Default cpu health checker.
- * Here's an example of how to use it.
+ * A {@link HealthChecker} that reports as unhealthy when the current + * CPU usage or CPU load exceeds threshold. For example: + *
{@code
  * final DefaultCpuHealthChecker cpuHealthChecker = HealthChecker.of(10, 10);
* final boolean healthy = cpuHealthChecker.isHealthy(); + * }
*/ // Forked from ProcessorMetrics.java in the micrometer core. final class DefaultCpuHealthChecker implements HealthChecker { From eda64c460a689d35ace7e0a1f75d519c1b979a98 Mon Sep 17 00:00:00 2001 From: Bue-von-hon Date: Fri, 9 Jun 2023 15:16:21 +0900 Subject: [PATCH 15/29] Fixed base on code review Modification: Fix(CpuHealthChecker): rename class and implemented a cache that statically creates and recycles MethodHandlers. Added method for test Fix(CpuHealthChecker): Modified to actually test for things like CPU usage and added relevant test cases. --- ...althChecker.java => CpuHealthChecker.java} | 41 +++++++-- .../healthcheck/CpuHealthCheckerTest.java | 87 +++++++++++++++++++ .../DefaultCpuHealthCheckerTest.java | 35 -------- 3 files changed, 120 insertions(+), 43 deletions(-) rename core/src/main/java/com/linecorp/armeria/server/healthcheck/{DefaultCpuHealthChecker.java => CpuHealthChecker.java} (72%) create mode 100644 core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java delete mode 100644 core/src/test/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthCheckerTest.java diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java similarity index 72% rename from core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java rename to core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 1abdb3961dd..01132b4dee7 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -23,6 +23,8 @@ import java.lang.management.OperatingSystemMXBean; import java.lang.reflect.Method; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.DoubleSupplier; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @@ -33,12 +35,12 @@ * A {@link HealthChecker} that reports as unhealthy when the current * CPU usage or CPU load exceeds threshold. For example: *
{@code
- * final DefaultCpuHealthChecker cpuHealthChecker = HealthChecker.of(10, 10);
+ * final CpuHealthChecker cpuHealthChecker = HealthChecker.of(10, 10);
* final boolean healthy = cpuHealthChecker.isHealthy(); * }
*/ // Forked from ProcessorMetrics.java in the micrometer core. -final class DefaultCpuHealthChecker implements HealthChecker { +final class CpuHealthChecker implements HealthChecker { private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = ImmutableList.of( "com.ibm.lang.management.OperatingSystemMXBean", // J9 @@ -61,13 +63,17 @@ final class DefaultCpuHealthChecker implements HealthChecker { private final double targetProcessCpuLoad; + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + private static final ConcurrentHashMap CACHE = new ConcurrentHashMap<>(); + /** * Instantiates a new Default cpu health checker. * * @param targetCpuUsage the target cpu usage * @param targetProcessCpuLoad the target process cpu usage */ - private DefaultCpuHealthChecker(int targetCpuUsage, int targetProcessCpuLoad) { + private CpuHealthChecker(double targetCpuUsage, double targetProcessCpuLoad) { this.targetCpuUsage = targetCpuUsage; this.targetProcessCpuLoad = targetProcessCpuLoad; this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); @@ -76,8 +82,8 @@ private DefaultCpuHealthChecker(int targetCpuUsage, int targetProcessCpuLoad) { this.processCpuUsage = detectMethod("getProcessCpuLoad"); } - public static DefaultCpuHealthChecker of(int targetCpuUsage, int targetProcessCpuLoad) { - return new DefaultCpuHealthChecker(targetCpuUsage, targetProcessCpuLoad); + public static CpuHealthChecker of(double targetCpuUsage, double targetProcessCpuLoad) { + return new CpuHealthChecker(targetCpuUsage, targetProcessCpuLoad); } /** @@ -85,15 +91,34 @@ public static DefaultCpuHealthChecker of(int targetCpuUsage, int targetProcessCp */ @Override public boolean isHealthy() { + assert systemCpuUsage != null; + assert processCpuUsage != null; final double currentSystemCpuUsage = invoke(systemCpuUsage); final double currentProcessCpuUsage = invoke(processCpuUsage); return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; } + @VisibleForTesting + public boolean isHealthy( + DoubleSupplier currentSystemCpuUsageSupplier, DoubleSupplier currentProcessCpuUsageSupplier) { + final double currentSystemCpuUsage = currentSystemCpuUsageSupplier.getAsDouble(); + final double currentProcessCpuUsage = currentProcessCpuUsageSupplier.getAsDouble(); + return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; + } + private double invoke(final Method method) { + MethodHandle mh = CACHE.get(method.getName()); + if (mh == null) { + try { + mh = LOOKUP.unreflect(method); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + + CACHE.put(method.getName(), mh); + } + try { - final MethodHandles.Lookup lookup = MethodHandles.lookup(); - final MethodHandle mh = lookup.unreflect(method); return (double) mh.invoke(operatingSystemBean); } catch (Throwable e) { return Double.NaN; @@ -115,7 +140,7 @@ private Method detectMethod(final String name) { private static Class getFirstClassFound(final List classNames) { for (String className : classNames) { try { - return Class.forName(className, false, DefaultCpuHealthChecker.class.getClassLoader()); + return Class.forName(className, false, CpuHealthChecker.class.getClassLoader()); } catch (ClassNotFoundException ignore) { } } diff --git a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java new file mode 100644 index 00000000000..aa7766e4fe9 --- /dev/null +++ b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2023 LINE Corporation + * + * LINE Corporation licenses this file to you 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: + * + * https://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 com.linecorp.armeria.server.healthcheck; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.Method; + +import org.junit.jupiter.api.Test; + +class CpuHealthCheckerTest { + + @Test + void testGatheringCpuUsageInformation1() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); + final Method processCpuUsage = cpuHealthChecker.processCpuUsage; + final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + assertNotNull(processCpuUsage); + assertNotNull(systemCpuUsage); + assertTrue(cpuHealthChecker.isHealthy(() -> 2.0, () -> 1.0)); + } + + @Test + void testGatheringCpuUsageInformation2() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); + final Method processCpuUsage = cpuHealthChecker.processCpuUsage; + final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + assertNotNull(processCpuUsage); + assertNotNull(systemCpuUsage); + assertTrue(cpuHealthChecker.isHealthy(() -> 3.0, () -> 1.0)); + } + + @Test + void testGatheringCpuUsageInformation3() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); + final Method processCpuUsage = cpuHealthChecker.processCpuUsage; + final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + assertNotNull(processCpuUsage); + assertNotNull(systemCpuUsage); + assertTrue(cpuHealthChecker.isHealthy(() -> 1.0, () -> 10.0)); + } + + @Test + void testGatheringCpuUsageInformation4() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); + final Method processCpuUsage = cpuHealthChecker.processCpuUsage; + final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + assertNotNull(processCpuUsage); + assertNotNull(systemCpuUsage); + assertFalse(cpuHealthChecker.isHealthy(() -> 4.0, () -> 10.0)); + } + + @Test + void testGatheringCpuUsageInformation5() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); + final Method processCpuUsage = cpuHealthChecker.processCpuUsage; + final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + assertNotNull(processCpuUsage); + assertNotNull(systemCpuUsage); + assertFalse(cpuHealthChecker.isHealthy(() -> 3.0, () -> 11.0)); + } + + @Test + void testGatheringCpuUsageInformation6() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); + final Method processCpuUsage = cpuHealthChecker.processCpuUsage; + final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + assertNotNull(processCpuUsage); + assertNotNull(systemCpuUsage); + assertFalse(cpuHealthChecker.isHealthy(() -> 4.0, () -> 11.0)); + } +} diff --git a/core/src/test/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthCheckerTest.java b/core/src/test/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthCheckerTest.java deleted file mode 100644 index bbaa9d014b8..00000000000 --- a/core/src/test/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthCheckerTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2023 LINE Corporation - * - * LINE Corporation licenses this file to you 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: - * - * https://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 com.linecorp.armeria.server.healthcheck; - - -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import java.lang.reflect.Method; - -import org.junit.jupiter.api.Test; - -class DefaultCpuHealthCheckerTest { - - @Test - void testGatheringCpuUsageInformation() { - final DefaultCpuHealthChecker cpuHealthChecker = DefaultCpuHealthChecker.of(10, 10); - final Method processCpuUsage = cpuHealthChecker.processCpuUsage; - final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; - assertNotNull(processCpuUsage); - assertNotNull(systemCpuUsage); - } -} From a1df8faac236999c3c299f60ea425d770eaeacbb Mon Sep 17 00:00:00 2001 From: kimtaehun Date: Mon, 28 Aug 2023 22:01:42 +0900 Subject: [PATCH 16/29] Resolves code review Motification: - Fix(CpuHealthCheckerTest): rename method to make it more meaningful - Fix(CpuHealthChecke): - rename targetCpuUsage, targetProcessCpuLoad to cpuUsageThreshold, processCpuLoadThreshold to make it more accurate - Modify Supplier, OperatingSystemMXBean, operatingSystemBeanClass, OPERATING_SYSTEM_BEAN_CLASS_NAMES, Method to static variables - Create a Static Block to Initialize those Static Variables - Modify methods used to initialize static variables to be static as well --- .../server/healthcheck/CpuHealthChecker.java | 98 +++++++++++-------- .../healthcheck/CpuHealthCheckerTest.java | 6 +- 2 files changed, 61 insertions(+), 43 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 01132b4dee7..cd40a0b1214 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -42,24 +42,41 @@ // Forked from ProcessorMetrics.java in the micrometer core. final class CpuHealthChecker implements HealthChecker { + private static final DoubleSupplier currentSystemCpuUsageSupplier; + + private static final DoubleSupplier currentProcessCpuUsageSupplier; + + private static final OperatingSystemMXBean operatingSystemBean; + + private static final Class operatingSystemBeanClass; + private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = ImmutableList.of( "com.ibm.lang.management.OperatingSystemMXBean", // J9 "com.sun.management.OperatingSystemMXBean" // HotSpot ); - private final OperatingSystemMXBean operatingSystemBean; - - private final Class operatingSystemBeanClass; + @Nullable + @VisibleForTesting + static final Method systemCpuUsage; @Nullable @VisibleForTesting - final Method systemCpuUsage; + static final Method processCpuUsage; + + static { + operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES));; + operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); + systemCpuUsage = detectMethod("getSystemCpuLoad"); + processCpuUsage = detectMethod("getProcessCpuLoad"); + currentSystemCpuUsageSupplier = () -> invoke(systemCpuUsage); + currentProcessCpuUsageSupplier = () -> invoke(processCpuUsage); + } private final double targetCpuUsage; - @Nullable - @VisibleForTesting - final Method processCpuUsage; + private final DoubleSupplier systemCpuUsageSupplier; + + private final DoubleSupplier processCpuUsageSupplier; private final double targetProcessCpuLoad; @@ -70,43 +87,22 @@ final class CpuHealthChecker implements HealthChecker { /** * Instantiates a new Default cpu health checker. * - * @param targetCpuUsage the target cpu usage - * @param targetProcessCpuLoad the target process cpu usage + * @param cpuUsageThreshold the target cpu usage + * @param processCpuLoadThreshold the target process cpu usage */ - private CpuHealthChecker(double targetCpuUsage, double targetProcessCpuLoad) { - this.targetCpuUsage = targetCpuUsage; - this.targetProcessCpuLoad = targetProcessCpuLoad; - this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); - this.operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); - this.systemCpuUsage = detectMethod("getSystemCpuLoad"); - this.processCpuUsage = detectMethod("getProcessCpuLoad"); - } - - public static CpuHealthChecker of(double targetCpuUsage, double targetProcessCpuLoad) { - return new CpuHealthChecker(targetCpuUsage, targetProcessCpuLoad); + private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshold) { + this(cpuUsageThreshold, processCpuLoadThreshold, currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); } - /** - * Returns true if and only if System CPU Usage and Processes cpu usage is below the target usage. - */ - @Override - public boolean isHealthy() { - assert systemCpuUsage != null; - assert processCpuUsage != null; - final double currentSystemCpuUsage = invoke(systemCpuUsage); - final double currentProcessCpuUsage = invoke(processCpuUsage); - return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; + private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshold, + DoubleSupplier systemCpuUsageSupplier, DoubleSupplier processCpuUsageSupplier) { + this.targetCpuUsage = cpuUsageThreshold; + this.targetProcessCpuLoad = processCpuLoadThreshold; + this.systemCpuUsageSupplier = systemCpuUsageSupplier; + this.processCpuUsageSupplier = processCpuUsageSupplier; } - @VisibleForTesting - public boolean isHealthy( - DoubleSupplier currentSystemCpuUsageSupplier, DoubleSupplier currentProcessCpuUsageSupplier) { - final double currentSystemCpuUsage = currentSystemCpuUsageSupplier.getAsDouble(); - final double currentProcessCpuUsage = currentProcessCpuUsageSupplier.getAsDouble(); - return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; - } - - private double invoke(final Method method) { + private static double invoke(final Method method) { MethodHandle mh = CACHE.get(method.getName()); if (mh == null) { try { @@ -126,7 +122,7 @@ private double invoke(final Method method) { } @Nullable - private Method detectMethod(final String name) { + private static Method detectMethod(final String name) { try { // ensure the Bean we have is actually an instance of the interface requireNonNull(operatingSystemBeanClass.cast(operatingSystemBean)); @@ -146,4 +142,26 @@ private static Class getFirstClassFound(final List classNames) { } return null; } + + public static CpuHealthChecker of(double targetCpuUsage, double targetProcessCpuLoad) { + return new CpuHealthChecker(targetCpuUsage, targetProcessCpuLoad); + } + + /** + * Returns true if and only if System CPU Usage and Processes cpu usage is below the target usage. + */ + @Override + public boolean isHealthy() { + final double currentSystemCpuUsage = systemCpuUsageSupplier.getAsDouble(); + final double currentProcessCpuUsage = processCpuUsageSupplier.getAsDouble(); + return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; + } + + @VisibleForTesting + boolean isHealthy( + DoubleSupplier currentSystemCpuUsageSupplier, DoubleSupplier currentProcessCpuUsageSupplier) { + final double currentSystemCpuUsage = currentSystemCpuUsageSupplier.getAsDouble(); + final double currentProcessCpuUsage = currentProcessCpuUsageSupplier.getAsDouble(); + return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; + } } diff --git a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java index aa7766e4fe9..461a20f6a99 100644 --- a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java @@ -26,7 +26,7 @@ class CpuHealthCheckerTest { @Test - void testGatheringCpuUsageInformation1() { + void shouldGatherCpuUsageInformationAndCheckHealth() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); final Method processCpuUsage = cpuHealthChecker.processCpuUsage; final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; @@ -36,7 +36,7 @@ void testGatheringCpuUsageInformation1() { } @Test - void testGatheringCpuUsageInformation2() { + void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryCpuUsage() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); final Method processCpuUsage = cpuHealthChecker.processCpuUsage; final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; @@ -46,7 +46,7 @@ void testGatheringCpuUsageInformation2() { } @Test - void testGatheringCpuUsageInformation3() { + void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryProcessUsage() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); final Method processCpuUsage = cpuHealthChecker.processCpuUsage; final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; From 0b14883a9f835a10366c02bf1e5ab7b3d65c9ba2 Mon Sep 17 00:00:00 2001 From: kimtaehun Date: Thu, 7 Sep 2023 22:35:26 +0900 Subject: [PATCH 17/29] Fix lint --- .../armeria/server/healthcheck/CpuHealthChecker.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index cd40a0b1214..30215422608 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -64,7 +64,7 @@ final class CpuHealthChecker implements HealthChecker { static final Method processCpuUsage; static { - operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES));; + operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); systemCpuUsage = detectMethod("getSystemCpuLoad"); processCpuUsage = detectMethod("getProcessCpuLoad"); @@ -91,7 +91,8 @@ final class CpuHealthChecker implements HealthChecker { * @param processCpuLoadThreshold the target process cpu usage */ private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshold) { - this(cpuUsageThreshold, processCpuLoadThreshold, currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); + this(cpuUsageThreshold, processCpuLoadThreshold, + currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); } private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshold, From 9d7cd921c3900ca2834aa5b05acb66be015e0c69 Mon Sep 17 00:00:00 2001 From: "taehun.kim" Date: Wed, 15 Nov 2023 14:12:50 +0900 Subject: [PATCH 18/29] Optimize CPU Health Check Implementations Motivation: Base on the code review, To streamline the efficiency and maintainability of the CPU health checking process, a refactor was needed to enhance code clarity, reduce redundancy. Motification: - Introduced `Logger` for improved logging capabilities when method detection fails. - Utilized `MethodHandles.Lookup` for method invocation instead of maintaining a method cache, reducing memory footprint. - Added `@Nullable` annotation to better represent potential `null` states in method handles. - Simplified `isHealthy` method by delegating to an overloaded method. Result: The CPU health checker's implementation is now more maintainable and less prone to errors, with the ability to handle future changes in a single, unified location. --- .../server/healthcheck/CpuHealthChecker.java | 54 ++++++++++--------- .../healthcheck/CpuHealthCheckerTest.java | 26 ++++----- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 30215422608..4ffd7674da4 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -23,9 +23,11 @@ import java.lang.management.OperatingSystemMXBean; import java.lang.reflect.Method; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; import java.util.function.DoubleSupplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @@ -41,11 +43,15 @@ */ // Forked from ProcessorMetrics.java in the micrometer core. final class CpuHealthChecker implements HealthChecker { + private static final Logger logger = LoggerFactory.getLogger(CpuHealthChecker.class); + + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); private static final DoubleSupplier currentSystemCpuUsageSupplier; private static final DoubleSupplier currentProcessCpuUsageSupplier; + @Nullable private static final OperatingSystemMXBean operatingSystemBean; private static final Class operatingSystemBeanClass; @@ -57,16 +63,17 @@ final class CpuHealthChecker implements HealthChecker { @Nullable @VisibleForTesting - static final Method systemCpuUsage; + static final MethodHandle systemCpuUsage; @Nullable @VisibleForTesting - static final Method processCpuUsage; + static final MethodHandle processCpuUsage; static { operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); - systemCpuUsage = detectMethod("getSystemCpuLoad"); + final MethodHandle getCpuLoad = detectMethod("getCpuLoad"); + systemCpuUsage = getCpuLoad != null ? getCpuLoad : detectMethod("getSystemCpuLoad"); processCpuUsage = detectMethod("getProcessCpuLoad"); currentSystemCpuUsageSupplier = () -> invoke(systemCpuUsage); currentProcessCpuUsageSupplier = () -> invoke(processCpuUsage); @@ -80,10 +87,6 @@ final class CpuHealthChecker implements HealthChecker { private final double targetProcessCpuLoad; - private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - - private static final ConcurrentHashMap CACHE = new ConcurrentHashMap<>(); - /** * Instantiates a new Default cpu health checker. * @@ -103,16 +106,9 @@ private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshol this.processCpuUsageSupplier = processCpuUsageSupplier; } - private static double invoke(final Method method) { - MethodHandle mh = CACHE.get(method.getName()); + private static double invoke(@Nullable MethodHandle mh) { if (mh == null) { - try { - mh = LOOKUP.unreflect(method); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - - CACHE.put(method.getName(), mh); + return Double.NaN; } try { @@ -123,12 +119,24 @@ private static double invoke(final Method method) { } @Nullable - private static Method detectMethod(final String name) { + @SuppressWarnings("ReturnValueIgnored") + private static MethodHandle detectMethod(final String name) { + if (operatingSystemBeanClass == null) { + return null; + } try { // ensure the Bean we have is actually an instance of the interface - requireNonNull(operatingSystemBeanClass.cast(operatingSystemBean)); - return operatingSystemBeanClass.getMethod(name); - } catch (ClassCastException | NoSuchMethodException | SecurityException e) { + operatingSystemBeanClass.cast(operatingSystemBean); + final Method method = operatingSystemBeanClass.getMethod(name); + return LOOKUP.unreflect(method); + } catch (ClassCastException | NoSuchMethodException | SecurityException | IllegalAccessException e) { + logger.warn( + "Failed to detect method {}.{} for {}", + operatingSystemBeanClass.getSimpleName(), + name, + CpuHealthChecker.class.getSimpleName(), + e + ); return null; } } @@ -153,9 +161,7 @@ public static CpuHealthChecker of(double targetCpuUsage, double targetProcessCpu */ @Override public boolean isHealthy() { - final double currentSystemCpuUsage = systemCpuUsageSupplier.getAsDouble(); - final double currentProcessCpuUsage = processCpuUsageSupplier.getAsDouble(); - return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; + return isHealthy(systemCpuUsageSupplier, processCpuUsageSupplier); } @VisibleForTesting diff --git a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java index 461a20f6a99..df9a458766d 100644 --- a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java @@ -19,7 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.lang.reflect.Method; +import java.lang.invoke.MethodHandle; import org.junit.jupiter.api.Test; @@ -28,8 +28,8 @@ class CpuHealthCheckerTest { @Test void shouldGatherCpuUsageInformationAndCheckHealth() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final Method processCpuUsage = cpuHealthChecker.processCpuUsage; - final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); assertTrue(cpuHealthChecker.isHealthy(() -> 2.0, () -> 1.0)); @@ -38,8 +38,8 @@ void shouldGatherCpuUsageInformationAndCheckHealth() { @Test void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryCpuUsage() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final Method processCpuUsage = cpuHealthChecker.processCpuUsage; - final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); assertTrue(cpuHealthChecker.isHealthy(() -> 3.0, () -> 1.0)); @@ -48,8 +48,8 @@ void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryCpuUsage() { @Test void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryProcessUsage() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final Method processCpuUsage = cpuHealthChecker.processCpuUsage; - final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); assertTrue(cpuHealthChecker.isHealthy(() -> 1.0, () -> 10.0)); @@ -58,8 +58,8 @@ void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryProcessUsage() { @Test void testGatheringCpuUsageInformation4() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final Method processCpuUsage = cpuHealthChecker.processCpuUsage; - final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); assertFalse(cpuHealthChecker.isHealthy(() -> 4.0, () -> 10.0)); @@ -68,8 +68,8 @@ void testGatheringCpuUsageInformation4() { @Test void testGatheringCpuUsageInformation5() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final Method processCpuUsage = cpuHealthChecker.processCpuUsage; - final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); assertFalse(cpuHealthChecker.isHealthy(() -> 3.0, () -> 11.0)); @@ -78,8 +78,8 @@ void testGatheringCpuUsageInformation5() { @Test void testGatheringCpuUsageInformation6() { final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final Method processCpuUsage = cpuHealthChecker.processCpuUsage; - final Method systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); assertFalse(cpuHealthChecker.isHealthy(() -> 4.0, () -> 11.0)); From f6ef4589f482586a11315d96c4dc36d7580eb3c0 Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Wed, 31 Jan 2024 08:08:21 +0900 Subject: [PATCH 19/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java Co-authored-by: jrhee17 --- .../linecorp/armeria/server/healthcheck/CpuHealthChecker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 4ffd7674da4..6c9b46af39d 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -73,8 +73,8 @@ final class CpuHealthChecker implements HealthChecker { operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); final MethodHandle getCpuLoad = detectMethod("getCpuLoad"); - systemCpuUsage = getCpuLoad != null ? getCpuLoad : detectMethod("getSystemCpuLoad"); - processCpuUsage = detectMethod("getProcessCpuLoad"); + systemCpuLoad = getCpuLoad != null ? getCpuLoad : detectMethod("getSystemCpuLoad"); + processCpuLoad = detectMethod("getProcessCpuLoad"); currentSystemCpuUsageSupplier = () -> invoke(systemCpuUsage); currentProcessCpuUsageSupplier = () -> invoke(processCpuUsage); } From a76691900220c77a5c35a515b463cfbd6cd4c473 Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Wed, 31 Jan 2024 08:09:12 +0900 Subject: [PATCH 20/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java Co-authored-by: jrhee17 --- .../armeria/server/healthcheck/CpuHealthChecker.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 6c9b46af39d..b79da2e5b68 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -130,13 +130,8 @@ private static MethodHandle detectMethod(final String name) { final Method method = operatingSystemBeanClass.getMethod(name); return LOOKUP.unreflect(method); } catch (ClassCastException | NoSuchMethodException | SecurityException | IllegalAccessException e) { - logger.warn( - "Failed to detect method {}.{} for {}", - operatingSystemBeanClass.getSimpleName(), - name, - CpuHealthChecker.class.getSimpleName(), - e - ); + logger.warn("Failed to detect method {}.{} for {}", operatingSystemBeanClass.getSimpleName(), + name, CpuHealthChecker.class.getSimpleName(), e); return null; } } From fad11551074e55faaac31633fc2869f377660a5f Mon Sep 17 00:00:00 2001 From: Bue-Von-Hun Date: Mon, 26 Feb 2024 15:38:56 +0900 Subject: [PATCH 21/29] Resolves code review --- .../server/healthcheck/CpuHealthChecker.java | 28 +++++++--- .../healthcheck/CpuHealthCheckerTest.java | 54 +++++++++---------- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index b79da2e5b68..3f193fe43a7 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -15,6 +15,8 @@ */ package com.linecorp.armeria.server.healthcheck; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; import java.lang.invoke.MethodHandle; @@ -63,11 +65,11 @@ final class CpuHealthChecker implements HealthChecker { @Nullable @VisibleForTesting - static final MethodHandle systemCpuUsage; + static final MethodHandle systemCpuLoad; @Nullable @VisibleForTesting - static final MethodHandle processCpuUsage; + static final MethodHandle processCpuLoad; static { operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); @@ -75,8 +77,8 @@ final class CpuHealthChecker implements HealthChecker { final MethodHandle getCpuLoad = detectMethod("getCpuLoad"); systemCpuLoad = getCpuLoad != null ? getCpuLoad : detectMethod("getSystemCpuLoad"); processCpuLoad = detectMethod("getProcessCpuLoad"); - currentSystemCpuUsageSupplier = () -> invoke(systemCpuUsage); - currentProcessCpuUsageSupplier = () -> invoke(processCpuUsage); + currentSystemCpuUsageSupplier = () -> invoke(systemCpuLoad); + currentProcessCpuUsageSupplier = () -> invoke(processCpuLoad); } private final double targetCpuUsage; @@ -98,12 +100,22 @@ private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshol currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); } - private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshold, + private CpuHealthChecker(double targetCpuUsage, double targetProcessCpuLoad, DoubleSupplier systemCpuUsageSupplier, DoubleSupplier processCpuUsageSupplier) { - this.targetCpuUsage = cpuUsageThreshold; - this.targetProcessCpuLoad = processCpuLoadThreshold; + checkArgument(targetCpuUsage >= 0 && targetCpuUsage <= 1.0, + "cpuUsage: %s (expected: 0 <= cpuUsage <= 1)", targetCpuUsage); + checkArgument(targetProcessCpuLoad >= 0 && targetProcessCpuLoad <= 1.0, + "processCpuLoad: %s (expected: 0 <= processCpuLoad <= 1)", targetProcessCpuLoad); + this.targetCpuUsage = targetCpuUsage; + this.targetProcessCpuLoad = targetProcessCpuLoad; this.systemCpuUsageSupplier = systemCpuUsageSupplier; this.processCpuUsageSupplier = processCpuUsageSupplier; + checkState(operatingSystemBeanClass != null, "Unable to find an 'OperatingSystemMXBean' class"); + checkState(operatingSystemBean != null, "Unable to find an 'OperatingSystemMXBean'"); + checkState(systemCpuLoad != null, "Unable to find the method 'OperatingSystemMXBean.getCpuLoad'" + + " or 'OperatingSystemMXBean.getSystemCpuLoad'"); + checkState(processCpuLoad != null, + "Unable to find the method 'OperatingSystemMXBean.getProcessCpuLoad'"); } private static double invoke(@Nullable MethodHandle mh) { @@ -147,7 +159,7 @@ private static Class getFirstClassFound(final List classNames) { return null; } - public static CpuHealthChecker of(double targetCpuUsage, double targetProcessCpuLoad) { + static CpuHealthChecker of(double targetCpuUsage, double targetProcessCpuLoad) { return new CpuHealthChecker(targetCpuUsage, targetProcessCpuLoad); } diff --git a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java index df9a458766d..5f4d45825e5 100644 --- a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java @@ -27,61 +27,61 @@ class CpuHealthCheckerTest { @Test void shouldGatherCpuUsageInformationAndCheckHealth() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); - assertTrue(cpuHealthChecker.isHealthy(() -> 2.0, () -> 1.0)); + assertTrue(cpuHealthChecker.isHealthy(() -> 0.2, () -> 0.01)); } @Test void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryCpuUsage() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); - assertTrue(cpuHealthChecker.isHealthy(() -> 3.0, () -> 1.0)); + assertTrue(cpuHealthChecker.isHealthy(() -> 0.3, () -> 0.01)); } @Test void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryProcessUsage() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); - assertTrue(cpuHealthChecker.isHealthy(() -> 1.0, () -> 10.0)); + assertTrue(cpuHealthChecker.isHealthy(() -> 0.01, () -> 0.1)); } @Test - void testGatheringCpuUsageInformation4() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; + void testSystemCpuLoadExceedsTargetCpuUsage() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); - assertFalse(cpuHealthChecker.isHealthy(() -> 4.0, () -> 10.0)); + assertFalse(cpuHealthChecker.isHealthy(() -> 0.4, () -> 0.1)); } @Test - void testGatheringCpuUsageInformation5() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; + void testProcessCpuLoadExceedsTargetProcessCpuUsage() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); - assertFalse(cpuHealthChecker.isHealthy(() -> 3.0, () -> 11.0)); + assertFalse(cpuHealthChecker.isHealthy(() -> 0.3, () -> 0.11)); } @Test - void testGatheringCpuUsageInformation6() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(3.0, 10); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuUsage; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuUsage; + void testExceedsBoth() { + final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); + final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; + final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; assertNotNull(processCpuUsage); assertNotNull(systemCpuUsage); - assertFalse(cpuHealthChecker.isHealthy(() -> 4.0, () -> 11.0)); + assertFalse(cpuHealthChecker.isHealthy(() -> 0.4, () -> 0.11)); } } From 29048d342ab7176b3cb25416a33c5b77e09541fa Mon Sep 17 00:00:00 2001 From: Bue-Von-Hun Date: Mon, 26 Feb 2024 16:15:50 +0900 Subject: [PATCH 22/29] Rewrite the test correctly --- .../server/healthcheck/CpuHealthChecker.java | 27 ++++---- .../healthcheck/CpuHealthCheckerTest.java | 65 ++----------------- 2 files changed, 17 insertions(+), 75 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 3f193fe43a7..ad43b761196 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -64,12 +64,10 @@ final class CpuHealthChecker implements HealthChecker { ); @Nullable - @VisibleForTesting - static final MethodHandle systemCpuLoad; + private static final MethodHandle systemCpuLoad; @Nullable - @VisibleForTesting - static final MethodHandle processCpuLoad; + private static final MethodHandle processCpuLoad; static { operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); @@ -81,13 +79,15 @@ final class CpuHealthChecker implements HealthChecker { currentProcessCpuUsageSupplier = () -> invoke(processCpuLoad); } - private final double targetCpuUsage; - private final DoubleSupplier systemCpuUsageSupplier; private final DoubleSupplier processCpuUsageSupplier; - private final double targetProcessCpuLoad; + @VisibleForTesting + final double targetProcessCpuLoad; + + @VisibleForTesting + final double targetSystemCpuUsage; /** * Instantiates a new Default cpu health checker. @@ -100,13 +100,13 @@ private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshol currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); } - private CpuHealthChecker(double targetCpuUsage, double targetProcessCpuLoad, + private CpuHealthChecker(double targetSystemCpuUsage, double targetProcessCpuLoad, DoubleSupplier systemCpuUsageSupplier, DoubleSupplier processCpuUsageSupplier) { - checkArgument(targetCpuUsage >= 0 && targetCpuUsage <= 1.0, - "cpuUsage: %s (expected: 0 <= cpuUsage <= 1)", targetCpuUsage); + checkArgument(targetSystemCpuUsage >= 0 && targetSystemCpuUsage <= 1.0, + "cpuUsage: %s (expected: 0 <= cpuUsage <= 1)", targetSystemCpuUsage); checkArgument(targetProcessCpuLoad >= 0 && targetProcessCpuLoad <= 1.0, "processCpuLoad: %s (expected: 0 <= processCpuLoad <= 1)", targetProcessCpuLoad); - this.targetCpuUsage = targetCpuUsage; + this.targetSystemCpuUsage = targetSystemCpuUsage; this.targetProcessCpuLoad = targetProcessCpuLoad; this.systemCpuUsageSupplier = systemCpuUsageSupplier; this.processCpuUsageSupplier = processCpuUsageSupplier; @@ -171,11 +171,10 @@ public boolean isHealthy() { return isHealthy(systemCpuUsageSupplier, processCpuUsageSupplier); } - @VisibleForTesting - boolean isHealthy( + private boolean isHealthy( DoubleSupplier currentSystemCpuUsageSupplier, DoubleSupplier currentProcessCpuUsageSupplier) { final double currentSystemCpuUsage = currentSystemCpuUsageSupplier.getAsDouble(); final double currentProcessCpuUsage = currentProcessCpuUsageSupplier.getAsDouble(); - return currentSystemCpuUsage <= targetCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; + return currentSystemCpuUsage <= targetSystemCpuUsage && currentProcessCpuUsage <= targetProcessCpuLoad; } } diff --git a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java index 5f4d45825e5..747e2ebbf71 100644 --- a/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/healthcheck/CpuHealthCheckerTest.java @@ -15,11 +15,7 @@ */ package com.linecorp.armeria.server.healthcheck; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.lang.invoke.MethodHandle; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.junit.jupiter.api.Test; @@ -27,61 +23,8 @@ class CpuHealthCheckerTest { @Test void shouldGatherCpuUsageInformationAndCheckHealth() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; - assertNotNull(processCpuUsage); - assertNotNull(systemCpuUsage); - assertTrue(cpuHealthChecker.isHealthy(() -> 0.2, () -> 0.01)); - } - - @Test - void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryCpuUsage() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; - assertNotNull(processCpuUsage); - assertNotNull(systemCpuUsage); - assertTrue(cpuHealthChecker.isHealthy(() -> 0.3, () -> 0.01)); - } - - @Test - void shouldGatherCpuUsageInformationAndCheckHealthWithBoundaryProcessUsage() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; - assertNotNull(processCpuUsage); - assertNotNull(systemCpuUsage); - assertTrue(cpuHealthChecker.isHealthy(() -> 0.01, () -> 0.1)); - } - - @Test - void testSystemCpuLoadExceedsTargetCpuUsage() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; - assertNotNull(processCpuUsage); - assertNotNull(systemCpuUsage); - assertFalse(cpuHealthChecker.isHealthy(() -> 0.4, () -> 0.1)); - } - - @Test - void testProcessCpuLoadExceedsTargetProcessCpuUsage() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; - assertNotNull(processCpuUsage); - assertNotNull(systemCpuUsage); - assertFalse(cpuHealthChecker.isHealthy(() -> 0.3, () -> 0.11)); - } - - @Test - void testExceedsBoth() { - final CpuHealthChecker cpuHealthChecker = CpuHealthChecker.of(0.3, 0.1); - final MethodHandle processCpuUsage = cpuHealthChecker.processCpuLoad; - final MethodHandle systemCpuUsage = cpuHealthChecker.systemCpuLoad; - assertNotNull(processCpuUsage); - assertNotNull(systemCpuUsage); - assertFalse(cpuHealthChecker.isHealthy(() -> 0.4, () -> 0.11)); + final CpuHealthChecker healthChecker = CpuHealthChecker.of(0.1, 0.3); + assertNotEquals(Double.NaN, healthChecker.targetSystemCpuUsage); + assertNotEquals(Double.NaN, healthChecker.targetProcessCpuLoad); } } From 5535d6a579283ee3749d633840a8b498285b229a Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:57:09 +0900 Subject: [PATCH 23/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java Co-authored-by: jrhee17 --- .../linecorp/armeria/server/healthcheck/CpuHealthChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index ad43b761196..245add2469c 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -70,7 +70,7 @@ final class CpuHealthChecker implements HealthChecker { private static final MethodHandle processCpuLoad; static { - operatingSystemBeanClass = requireNonNull(getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES)); + operatingSystemBeanClass = getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES); operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); final MethodHandle getCpuLoad = detectMethod("getCpuLoad"); systemCpuLoad = getCpuLoad != null ? getCpuLoad : detectMethod("getSystemCpuLoad"); From 759763b76a84b7fa314cbdb6cf7df7f6be3917e0 Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:57:22 +0900 Subject: [PATCH 24/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java Co-authored-by: jrhee17 --- .../linecorp/armeria/server/healthcheck/CpuHealthChecker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 245add2469c..502e6cc157d 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -56,6 +56,7 @@ final class CpuHealthChecker implements HealthChecker { @Nullable private static final OperatingSystemMXBean operatingSystemBean; + @Nullable private static final Class operatingSystemBeanClass; private static final List OPERATING_SYSTEM_BEAN_CLASS_NAMES = ImmutableList.of( From fb59ec472807e3139fd77a2911e5bb5036322f35 Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:57:38 +0900 Subject: [PATCH 25/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java Co-authored-by: jrhee17 --- .../linecorp/armeria/server/healthcheck/CpuHealthChecker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 502e6cc157d..e91dac5912a 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -160,8 +160,8 @@ private static Class getFirstClassFound(final List classNames) { return null; } - static CpuHealthChecker of(double targetCpuUsage, double targetProcessCpuLoad) { - return new CpuHealthChecker(targetCpuUsage, targetProcessCpuLoad); + static CpuHealthChecker of(double targetSystemCpuUsage, double targetProcessCpuUsage) { + return new CpuHealthChecker(targetSystemCpuUsage, targetProcessCpuUsage); } /** From d1a06e3240d3a7a16327077993d33a7f63546b97 Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:57:48 +0900 Subject: [PATCH 26/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java Co-authored-by: jrhee17 --- .../linecorp/armeria/server/healthcheck/CpuHealthChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index e91dac5912a..af51e1ddf64 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -108,7 +108,7 @@ private CpuHealthChecker(double targetSystemCpuUsage, double targetProcessCpuLoa checkArgument(targetProcessCpuLoad >= 0 && targetProcessCpuLoad <= 1.0, "processCpuLoad: %s (expected: 0 <= processCpuLoad <= 1)", targetProcessCpuLoad); this.targetSystemCpuUsage = targetSystemCpuUsage; - this.targetProcessCpuLoad = targetProcessCpuLoad; + this.targetProcessCpuUsage = targetProcessCpuUsage; this.systemCpuUsageSupplier = systemCpuUsageSupplier; this.processCpuUsageSupplier = processCpuUsageSupplier; checkState(operatingSystemBeanClass != null, "Unable to find an 'OperatingSystemMXBean' class"); From 1dda3170c3a1a752e1b57f92c621295b2c59cc84 Mon Sep 17 00:00:00 2001 From: kimtaehun <46879264+Bue-von-hon@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:57:58 +0900 Subject: [PATCH 27/29] Update core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java Co-authored-by: jrhee17 --- .../linecorp/armeria/server/healthcheck/CpuHealthChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index af51e1ddf64..4e89cc4ae8b 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -96,7 +96,7 @@ final class CpuHealthChecker implements HealthChecker { * @param cpuUsageThreshold the target cpu usage * @param processCpuLoadThreshold the target process cpu usage */ - private CpuHealthChecker(double cpuUsageThreshold, double processCpuLoadThreshold) { + private CpuHealthChecker(double targetSystemCpuUsage, double targetProcessCpuUsage) { this(cpuUsageThreshold, processCpuLoadThreshold, currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); } From 828e51a6b981b3eb58898bed5ebb90bd7e76159c Mon Sep 17 00:00:00 2001 From: Bue-Von-Hun Date: Fri, 22 Mar 2024 14:42:41 +0900 Subject: [PATCH 28/29] Add a factory method to an HealthChecker interface Motivation: Add a factory method so that users can actually use the CPU health checker. Modification: - Fix(HealthChecker): added a factory method. - Fix(CpuHealthChecker): removed factory method and added a little more clarity in the description. - Fix(CpuHealthCheckerTest): renamed the method and modified it to use the newly created factory method. Result: Users will be able to use the newly created health checker, and a detailed description will improve usability. --- .../server/healthcheck/CpuHealthChecker.java | 20 +++++++++---------- .../server/healthcheck/HealthChecker.java | 11 ++++++++++ .../healthcheck/CpuHealthCheckerTest.java | 4 ++-- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 4e89cc4ae8b..9431f56791b 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -17,7 +17,6 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; -import static java.util.Objects.requireNonNull; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -39,7 +38,10 @@ * A {@link HealthChecker} that reports as unhealthy when the current * CPU usage or CPU load exceeds threshold. For example: *
{@code
- * final CpuHealthChecker cpuHealthChecker = HealthChecker.of(10, 10);
+ * final CpuHealthChecker cpuHealthChecker = HealthChecker.of(0.1, 0.1); + * + * // Returns false if either is greater than 10%, + * // or true if both are less than or equal to 10%. * final boolean healthy = cpuHealthChecker.isHealthy(); * }
*/ @@ -93,11 +95,11 @@ final class CpuHealthChecker implements HealthChecker { /** * Instantiates a new Default cpu health checker. * - * @param cpuUsageThreshold the target cpu usage - * @param processCpuLoadThreshold the target process cpu usage + * @param targetSystemCpuUsage the target cpu usage + * @param targetProcessCpuUsage the target process cpu usage */ - private CpuHealthChecker(double targetSystemCpuUsage, double targetProcessCpuUsage) { - this(cpuUsageThreshold, processCpuLoadThreshold, + CpuHealthChecker(double targetSystemCpuUsage, double targetProcessCpuUsage) { + this(targetSystemCpuUsage, targetProcessCpuUsage, currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); } @@ -108,7 +110,7 @@ private CpuHealthChecker(double targetSystemCpuUsage, double targetProcessCpuLoa checkArgument(targetProcessCpuLoad >= 0 && targetProcessCpuLoad <= 1.0, "processCpuLoad: %s (expected: 0 <= processCpuLoad <= 1)", targetProcessCpuLoad); this.targetSystemCpuUsage = targetSystemCpuUsage; - this.targetProcessCpuUsage = targetProcessCpuUsage; + this.targetProcessCpuLoad = targetProcessCpuLoad; this.systemCpuUsageSupplier = systemCpuUsageSupplier; this.processCpuUsageSupplier = processCpuUsageSupplier; checkState(operatingSystemBeanClass != null, "Unable to find an 'OperatingSystemMXBean' class"); @@ -160,10 +162,6 @@ private static Class getFirstClassFound(final List classNames) { return null; } - static CpuHealthChecker of(double targetSystemCpuUsage, double targetProcessCpuUsage) { - return new CpuHealthChecker(targetSystemCpuUsage, targetProcessCpuUsage); - } - /** * Returns true if and only if System CPU Usage and Processes cpu usage is below the target usage. */ diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java index 17fa76e253f..78892b3dde1 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java @@ -88,6 +88,17 @@ static ListenableHealthChecker of(Supplier Date: Tue, 26 Mar 2024 21:00:31 +0900 Subject: [PATCH 29/29] supplement javadocs --- .../armeria/server/healthcheck/CpuHealthChecker.java | 2 +- .../armeria/server/healthcheck/HealthChecker.java | 12 +++++++++--- .../server/healthcheck/CpuHealthCheckerTest.java | 9 +++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java index 9431f56791b..bc040182a72 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java @@ -100,7 +100,7 @@ final class CpuHealthChecker implements HealthChecker { */ CpuHealthChecker(double targetSystemCpuUsage, double targetProcessCpuUsage) { this(targetSystemCpuUsage, targetProcessCpuUsage, - currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); + currentSystemCpuUsageSupplier, currentProcessCpuUsageSupplier); } private CpuHealthChecker(double targetSystemCpuUsage, double targetProcessCpuLoad, diff --git a/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java b/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java index 78892b3dde1..61e5f84d84a 100644 --- a/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java +++ b/core/src/main/java/com/linecorp/armeria/server/healthcheck/HealthChecker.java @@ -23,6 +23,8 @@ import java.util.concurrent.CompletionStage; import java.util.function.Supplier; +import com.sun.management.OperatingSystemMXBean; + import com.linecorp.armeria.common.CommonPools; import com.linecorp.armeria.common.annotation.UnstableApi; import com.linecorp.armeria.server.Server; @@ -89,13 +91,17 @@ static ListenableHealthChecker of(Supplier