-
Notifications
You must be signed in to change notification settings - Fork 927
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
Added DefaultCpuHealthChecker #4673
Conversation
Motivation: Resolves part of line#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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall! Left some minor comments
import java.lang.reflect.Method; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also leave a link where this class was forked from?
// Forked from https://github.com/micrometer-metrics/micrometer/blob/8339d57bef8689beb8d7a18b429a166f6595f2af/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/ProcessorMetrics.java |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i added!
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public class DefaultCpuHealthChecker implements HealthChecker{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also add integration tests for this class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm struggling with writing tests.😭
To do the test, need to modify the CPU usage of the system and it is very difficult.
I'm considering passing a Method class through the constructor.(Dependency Injection with @VisibleForTesting annotation).
p.s.
I looked at micrometer's ProcessorMetricsTest.java and spring-boot's AvailabilityStateHealthIndicatorTests.java but didn't get much help.😭
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To do the test, need to modify the CPU usage of the system and it is very difficult.
I don't think this is necessary 😅 I think just verifying that DefaultCpuHealthChecker
gathers system cpu usage information is enough.
We may expose targetCpuUsage
, targetProcessCpuLoad
(with @VisibleForTesting
) and check that they are not NaN for example.
|
||
private final double targetCpuUsage; | ||
|
||
public DefaultCpuHealthChecker(final double targetCpuUsage) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we accept arguments for both targetSystemCpuLoad
and targetProcessCpuLoad
so that users can configure limits separately?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i added!
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
private Class<?> getFirstClassFound(final List<String> classNames) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private Class<?> getFirstClassFound(final List<String> classNames) { | |
@Nullable | |
private Class<?> getFirstClassFound(final List<String> classNames) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i added!
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jrhee17 Fixed based on a code review!
p.s.
Another PR on the same issue commented on the ratio-based.
I thought it was reasonable so applied it!
import java.lang.reflect.Method; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i added!
|
||
private final double targetCpuUsage; | ||
|
||
public DefaultCpuHealthChecker(final double targetCpuUsage) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i added!
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public class DefaultCpuHealthChecker implements HealthChecker{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm struggling with writing tests.😭
To do the test, need to modify the CPU usage of the system and it is very difficult.
I'm considering passing a Method class through the constructor.(Dependency Injection with @VisibleForTesting annotation).
p.s.
I looked at micrometer's ProcessorMetricsTest.java and spring-boot's AvailabilityStateHealthIndicatorTests.java but didn't get much help.😭
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
private Class<?> getFirstClassFound(final List<String> classNames) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i added!
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
this.targetCpuUsage = (double) cpuUsage / cpuIdle; | ||
this.targetProcessCpuLoad = (double) processCpuUsage / processCpuIdle; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question) I'm unsure why we're dividing usage by idleness. Can't we just receive two doubles targetCpuUsage
, targetProcessCpuLoad
as parameters?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using two is more readable. fixed it!
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
public DefaultCpuHealthChecker(final int cpuUsage, final int cpuIdle, | ||
final int processCpuUsage, final int processCpuIdle) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of exposing this public constructor, can we use a static factory method to instantiate this checker?
public DefaultCpuHealthChecker(final int cpuUsage, final int cpuIdle, | |
final int processCpuUsage, final int processCpuIdle) { | |
private DefaultCpuHealthChecker(final int cpuUsage, final int cpuIdle, | |
final int processCpuUsage, final int processCpuIdle) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jrhee17 i Fixed it! And moved the factory method I created earlier to DefaultCpuHealthChecker.
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
/** | ||
* Forked from <a href="https://github.com/micrometer-metrics/micrometer/blob/8339d57bef8689beb8d7a18b429a166f6595f2af/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/ProcessorMetrics.java">ProcessorMetrics.java</a> in the micrometer core. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be part of Javadoc. Could you use //
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Fixed!
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
|
||
private double invoke(final Method method) { | ||
try { | ||
return (double) method.invoke(operatingSystemBean); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method will be frequently invoked whenever HealthCheckService
receives a request, hence MethodHandles
might be a better choice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the lookup#unreflect method, extracted the MethodHandle object from the Method class!
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
/** | ||
* Forked from <a href="https://github.com/micrometer-metrics/micrometer/blob/8339d57bef8689beb8d7a18b429a166f6595f2af/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/ProcessorMetrics.java">ProcessorMetrics.java</a> in the micrometer core. | ||
*/ | ||
public class DefaultCpuHealthChecker implements HealthChecker { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we hide the implementation from the public API, we can get more freedom on changes.
Should we add a factory method of this class to HealthChecker
and make this package-private?
// The simplest one.
HealthChecker.ofCpu(cpuUsage);
// A complex configuation.
HealthChecker.ofCpu(cpuUsage, cpuIdle...);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha, so let's make this class pakage-private and add a factory method to HealthChecker!
…aultCpuHealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…aultCpuHealthChecker.java Co-authored-by: Ikhun Um <[email protected]>
…aultCpuHealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…aultCpuHealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…aultCpuHealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…aultCpuHealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…aultCpuHealthChecker.java Co-authored-by: Trustin Lee <[email protected]>
…aultCpuHealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…est 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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jrhee17 I sent a new commit based on the code review.
Hope you like it🙂
/** | ||
* Forked from <a href="https://github.com/micrometer-metrics/micrometer/blob/8339d57bef8689beb8d7a18b429a166f6595f2af/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/ProcessorMetrics.java">ProcessorMetrics.java</a> in the micrometer core. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Fixed!
this.targetCpuUsage = (double) cpuUsage / cpuIdle; | ||
this.targetProcessCpuLoad = (double) processCpuUsage / processCpuIdle; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using two is more readable. fixed it!
/** | ||
* Forked from <a href="https://github.com/micrometer-metrics/micrometer/blob/8339d57bef8689beb8d7a18b429a166f6595f2af/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/ProcessorMetrics.java">ProcessorMetrics.java</a> in the micrometer core. | ||
*/ | ||
public class DefaultCpuHealthChecker implements HealthChecker { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha, so let's make this class pakage-private and add a factory method to HealthChecker!
|
||
private double invoke(final Method method) { | ||
try { | ||
return (double) method.invoke(operatingSystemBean); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the lookup#unreflect method, extracted the MethodHandle object from the Method class!
Modification: - Move the static factory method to DefaultCpuHealthChecker.
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthChecker.java
Outdated
Show resolved
Hide resolved
core/src/test/java/com/linecorp/armeria/server/healthcheck/DefaultCpuHealthCheckerTest.java
Outdated
Show resolved
Hide resolved
…HealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…HealthChecker.java Co-authored-by: jrhee17 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I misunderstood your comment about testing.
I've rewritten the test correctly.
PTAL @jrhee17
core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java
Show resolved
Hide resolved
@jrhee17 gentle ping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry about the delay 😅 Looks like almost the last round for me!
core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/healthcheck/CpuHealthChecker.java
Outdated
Show resolved
Hide resolved
return null; | ||
} | ||
|
||
static CpuHealthChecker of(double targetCpuUsage, double targetProcessCpuLoad) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of:
- Moving this to
HealthChecker.java
- Renaming this method from
of
toofCpu
- Making this method public so that users can actually use this class
- Adding javadocs explaining what this health checker does, and what each parameter does
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw this comment late:
I'm fine if this is handled separately, I would just like to note that users won't be able to access this method since it is not public
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks great once @jrhee17 comments are addressed.
Thanks for your effort on this work! ❤️🚀
…HealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…HealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…HealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…HealthChecker.java Co-authored-by: jrhee17 <[email protected]>
…HealthChecker.java Co-authored-by: jrhee17 <[email protected]>
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.
@jrhee17 I've addressed everything you commented on. The fact that the factory method was mentioned twice, I felt it was important. I implemented it by adding a static method to the interface. It was the best I could do, as a way to keep compatibility across subclasses as much as possible. p.s. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a minor commit mostly fixing javadocs, but looks good to me! Thanks for your patience @Bue-von-hon ! 🙇 👍 🙇
Thanks a lot for your patience, @Bue-von-hon! |
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
Modifications:
Result:
A User can health-check with system-cpu-usage
p.s.
Implemented this by referencing ProcessorMetrics.java in the micrometer core.