[refactor] Refactor the comparison logic#3574
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the comparison logic in AlertExpressionEvalVisitor to fully support PromQL-style comparisons with an optional bool modifier and combinations of scalar/vector operands.
- Added optional
boolmodifier and distinct handling for scalar–scalar, scalar–vector, vector–scalar, and vector–vector comparisons. - Updated the ANTLR grammar (
AlertExpression.g4) to allow an optionalBOOLtoken in comparison expressions. - Added new unit tests in
AlertExpressionEvalVisitorTestcovering all comparison scenarios.
Reviewed Changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| hertzbeat-common/src/main/java/org/apache/hertzbeat/common/support/exception/ExpressionVisitorException.java | Introduces a custom ExpressionVisitorException for parse errors |
| hertzbeat-alerter/src/main/resources/expr/AlertExpression.g4 | Extends the comparison rule to include an optional BOOL modifier |
| hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/expr/AlertExpressionEvalVisitor.java | Refactors visitComparisonExpr to handle scalar/vector and bool |
| hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/expr/AlertExpressionEvalVisitorTest.java | Updates existing tests and adds new ones for comparison expressions |
Comments suppressed due to low confidence (2)
hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/expr/AlertExpressionEvalVisitor.java:305
- [nitpick] Method name
isValidValueis misleading because it returns true for invalid values (null or List). Consider renaming toisInvalidValueor inverting the logic for clarity.
private boolean isValidValue(Object val) {
hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/expr/AlertExpressionEvalVisitor.java:132
- Missing import for
java.util.stream.Collectors, which will cause a compile error when callingcollect(Collectors.toMap(...)).
.collect(Collectors.toMap(this::labelKey, item -> item, (existing, replacement) -> existing));
| case AlertExpressionParser.GE -> left >= right; | ||
| case AlertExpressionParser.LT -> left < right; | ||
| case AlertExpressionParser.LE -> left <= right; | ||
| case AlertExpressionParser.EQ -> left == right; |
There was a problem hiding this comment.
[nitpick] Using == to compare doubles can be unreliable due to floating‐point precision. Consider using Double.compare(left, right) == 0 or a tolerance-based comparison.
| case AlertExpressionParser.EQ -> left == right; | |
| case AlertExpressionParser.EQ -> Double.compare(left, right) == 0; |
| try { | ||
| return Double.parseDouble(text); | ||
| } catch (NumberFormatException e) { | ||
| throw new ExpressionVisitorException("number format exception", e); |
There was a problem hiding this comment.
The error message "number format exception" is too generic. Include the input text that failed to parse for better troubleshooting.
| throw new ExpressionVisitorException("number format exception", e); | |
| throw new ExpressionVisitorException("Failed to parse '" + text + "' as a double", e); |
| } | ||
|
|
||
| // scalar and vector | ||
| if (leftIsScalar) { |
There was a problem hiding this comment.
[nitpick] The branches for scalar–vector and vector–scalar comparisons share very similar logic. Consider extracting a helper method to reduce duplication.
|
Thank you for your PR. There is an example I would like to discuss with you. According to the current parsing rules, At present, only LiteralExpr(number) is regarded as a scalar. I think more judgment conditions may be needed to determine whether something is a scalar, such as whether there are labels in the metric query results. |
Hi, @MasamiYui thank you for your review. There are a few points regarding your question.
|
👍 I got it! |
|
@MasamiYui Oh, right, as of this PR, the semantic correctness should all be handled. Next, we should discuss the plans we mentioned earlier. When is the next meeting? We can discuss that. I remember @tomsun28 saying that the meeting time was posted on the public channel. How can I subscribe to this information? |
@Duansg please ref to : mailing_lists |


What's changed?
Refactor the comparison logic in
org.apache.hertzbeat.alert.expr.AlertExpressionEvalVisitor#visitComparisonExprFor details:
comparison binary operators.comparison binary operatorsfunction, and addscalar and scalar,scalar and vector, andvector and vector.boolmodifier.Checklist
Add or update API
// vector and vector



// vector and scalar



// scalar and vector



// scalar and scalar

