This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push:
new 12744bba02 Add `view_as_seq` function in MQE for listing metrics in
the given prioritized sequence (#11194)
12744bba02 is described below
commit 12744bba029a1566c7fb868bfcd32138bbb72cd9
Author: mrproliu <[email protected]>
AuthorDate: Wed Aug 9 11:59:49 2023 +0800
Add `view_as_seq` function in MQE for listing metrics in the given
prioritized sequence (#11194)
---
docs/en/api/metrics-query-expression.md | 52 +++++++++++++------
docs/en/changes/changes.md | 2 +-
.../apache/skywalking/mqe/rt/grammar/MQELexer.g4 | 3 ++
.../apache/skywalking/mqe/rt/grammar/MQEParser.g4 | 16 ++++--
.../apache/skywalking/mqe/rt/MQEVisitorBase.java | 28 +++++++---
.../mqe/rt/operation/LogicalFunctionOp.java | 60 ++++++++++++++++++++++
...FunctionOp.java => MathematicalFunctionOp.java} | 10 ++--
.../library/mqe/rt/LogicalFunctionOpTest.java | 59 +++++++++++++++++++++
...OpTest.java => MathematicalFunctionOpTest.java} | 16 +++---
.../apache/skywalking/library/mqe/rt/MockData.java | 1 +
test/e2e-v2/cases/mqe/expected/viewAsSeq-OP.yml | 31 +++++++++++
test/e2e-v2/cases/mqe/mqe-cases.yaml | 6 ++-
12 files changed, 242 insertions(+), 42 deletions(-)
diff --git a/docs/en/api/metrics-query-expression.md
b/docs/en/api/metrics-query-expression.md
index 4e67a93982..c7fd44874f 100644
--- a/docs/en/api/metrics-query-expression.md
+++ b/docs/en/api/metrics-query-expression.md
@@ -48,7 +48,7 @@ If we want to rename the label values to
`P50,P75,P90,P95,P99`, see [Relabel Ope
The `ExpressionResultType` of the expression is `TIME_SERIES_VALUES` and with
labels.
## Binary Operation
-Binary Operation is an operation that takes two expressions and performs a
calculation on their results.
+The binary Operation is an operation that takes two expressions and performs a
calculation on their results.
The following table lists the binary operations supported by MQE.
Expression:
@@ -71,11 +71,11 @@ service_sla / 100
```
### Result Type
-The result type of the expression please refer to the following table.
+For the result type of the expression, please refer to the following table.
### Binary Operation Rules
-The following table listed if the difference result types of the input
expressions could do this operation and the result type after the operation.
-The expression could on the left or right side of the operator.
+The following table lists if the different result types of the input
expressions could do this operation and the result type after the operation.
+The expression could be on the left or right side of the operator.
**Note**: If the expressions on both sides of the operator are the
`TIME_SERIES_VALUES with labels`, they should have the same labels for
calculation.
| Expression | Expression | Yes/No |
ExpressionResultType |
@@ -88,7 +88,7 @@ The expression could on the left or right side of the
operator.
| SORTED_LIST/RECORD_LIST | SORTED_LIST/RECORD_LIST | no |
|
## Aggregation Operation
-Aggregation Operation takes an expression and performs aggregate calculation
on its results.
+Aggregation Operation takes an expression and performs aggregate calculations
on its results.
Expression:
```text
@@ -112,14 +112,14 @@ avg(service_cpm)
```
### Result Type
-The different operator could impact the `ExpressionResultType`, please refer
to the above table.
+The different operators could impact the `ExpressionResultType`, please refer
to the above table.
-## Function Operation
-Function Operation takes an expression and performs function calculation on
its results.
+## Mathematical Operation
+Mathematical Operation takes an expression and performs mathematical
calculations on its results.
Expression:
```text
-<Function-Operator>(Expression, parameters)
+<Mathematical-Operator>(Expression, parameters)
```
| Operator | Definition
| parameters |
ExpressionResultType |
@@ -138,7 +138,7 @@ round(service_cpm / 60 , 2)
```
### Result Type
-The different operator could impact the `ExpressionResultType`, please refer
to the above table.
+The different operators could impact the `ExpressionResultType`, please refer
to the above table.
## TopN Operation
TopN Operation takes an expression and performs TopN calculation on its
results.
@@ -163,14 +163,14 @@ top_n(service_instance_cpm, 10, des)
According to the type of the metric, the `ExpressionResultType` of the
expression will be `SORTED_LIST` or `RECORD_LIST`.
## Relabel Operation
-Relabel Operation takes an expression and replace the label values to new
label values on its results.
+Relabel Operation takes an expression and replaces the label values with new
label values on its results.
Expression:
```text
relabel(Expression, _='<new_label_value_1>,...')
```
-`_` is the new label valuess of the metric after the label is relabeled, the
order of the new label values should be the same as the order of the label
values in the input expression result.
+`_` is the new label of the metric after the label is relabeled, the order of
the new label values should be the same as the order of the label values in the
input expression result.
For example:
If we want to query the `service_percentile` metric with the label values
`0,1,2,3,4`, and rename the label values to `P50,P75,P90,P95,P99`, we can use
the following expression:
@@ -183,7 +183,7 @@ relabel(service_percentile{_='0,1,2,3,4'},
_='P50,P75,P90,P95,P99')
Follow the input expression.
## AggregateLabels Operation
-AggregateLabels Operation takes an expression and performs aggregate
calculation on its `Labeled Value Metrics` results. It aggregates a group of
`TIME_SERIES_VALUES` into a single `TIME_SERIES_VALUES`.
+AggregateLabels Operation takes an expression and performs an aggregate
calculation on its `Labeled Value Metrics` results. It aggregates a group of
`TIME_SERIES_VALUES` into a single `TIME_SERIES_VALUES`.
Expression:
```text
@@ -194,11 +194,11 @@ aggregate_labels(Expression, parameter)
|-----------|-----------------------------------------------------|----------------------|
| avg | calculate avg value of a `Labeled Value Metrics` |
TIME_SERIES_VALUES |
| sum | calculate sum value of a `Labeled Value Metrics` |
TIME_SERIES_VALUES |
-| max | select maximum value from a `Labeled Value Metrics` |
TIME_SERIES_VALUES |
-| min | select minimum value from a `Labeled Value Metrics` |
TIME_SERIES_VALUES |
+| max | select the maximum value from a `Labeled Value Metrics` |
TIME_SERIES_VALUES |
+| min | select the minimum value from a `Labeled Value Metrics` |
TIME_SERIES_VALUES |
For example:
-If we want to query all redis command total rate, we can use the following
expression(`total_commands_rate` is a metric which recorded every command rate
in labeled value):
+If we want to query all Redis command total rates, we can use the following
expression(`total_commands_rate` is a metric which recorded every command rate
in labeled value):
```text
aggregate_labels(total_commands_rate, SUM)
@@ -206,3 +206,23 @@ aggregate_labels(total_commands_rate, SUM)
### Result Type
The ExpressionResultType of the aggregateLabels operation is
TIME_SERIES_VALUES.
+
+## Logical Operation
+### ViewAsSequence Operation
+ViewAsSequence operation represents the first not-null metric from the listing
metrics in the given prioritized sequence(left to right). It could also be
considered as a `short-circuit` of given metrics for the first value existing
metric.
+
+Expression:
+```text
+view_as_seq([<expression_1>, <expression_2>, ...])
+```
+
+For example:
+if the first expression value is empty but the second one is not empty, it
would return the result from the second expression.
+The following example would return the content of the **service_cpm** metric.
+
+```text
+view_as_seq(not_existing, service_cpm)
+```
+
+#### Result Type
+The result type is determined by the type of selected not-null metric
expression.
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index dd3f997d6d..9b3d23f433 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -67,7 +67,7 @@
* Add OpenSearch 2.8.0 to our client lib tests.
* Apply MQE on RabbitMQ Dashboards.
* Use listening mode for apollo implementation of dynamic configuration.
-
+* Add `view_as_seq` function in MQE for listing metrics in the given
prioritized sequence.
#### UI
diff --git
a/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
b/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
index 26e0ce2cbb..b7a870a6bc 100644
---
a/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
+++
b/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
@@ -63,6 +63,9 @@ ROUND: 'round';
// TopN
TOP_N: 'top_n';
+// ViewAsSeq
+VIEW_AS_SEQ: 'view_as_seq';
+
// Relabels
RELABELS: 'relabels';
diff --git
a/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
b/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
index 46e1c5f197..6851155970 100644
---
a/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
+++
b/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
@@ -28,13 +28,18 @@ expression
| expression addSub expression # addSubOp
| expression compare expression # compareOp
| aggregation L_PAREN expression R_PAREN # aggregationOp
- | function0 L_PAREN expression R_PAREN #function0OP
- | function1 L_PAREN expression COMMA parameter R_PAREN #function1OP
+ | mathematical_operator0 L_PAREN expression R_PAREN
#mathematicalOperator0OP
+ | mathematical_operator1 L_PAREN expression COMMA parameter R_PAREN
#mathematicalOperator1OP
+ | logical_operator L_PAREN expressionList R_PAREN #logicalOperatorOP
| topN L_PAREN metric COMMA parameter COMMA order R_PAREN #topNOP
| relabels L_PAREN expression COMMA label R_PAREN #relablesOP
| aggregateLabels L_PAREN expression COMMA aggregateLabelsFunc R_PAREN
#aggregateLabelsOp
;
+expressionList
+ : expression (COMMA expression)*
+ ;
+
expressionNode: metric| scalar;
addSub: ADD | SUB ;
@@ -57,14 +62,17 @@ aggregation:
AVG | COUNT | LATEST | SUM | MAX | MIN | ;
// 0 parameter function
-function0:
+mathematical_operator0:
ABS | CEIL | FLOOR;
// 1 parameter function
-function1:
+mathematical_operator1:
ROUND;
topN: TOP_N;
+logical_operator:
+ VIEW_AS_SEQ;
+
relabels: RELABELS;
parameter: INTEGER;
diff --git
a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
index 229e849d92..aa5c5d0277 100644
---
a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
+++
b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
@@ -27,7 +27,8 @@ import
org.apache.skywalking.mqe.rt.grammar.MQEParserBaseVisitor;
import org.apache.skywalking.mqe.rt.operation.AggregateLabelsOp;
import org.apache.skywalking.mqe.rt.operation.AggregationOp;
import org.apache.skywalking.mqe.rt.operation.BinaryOp;
-import org.apache.skywalking.mqe.rt.operation.FunctionOp;
+import org.apache.skywalking.mqe.rt.operation.LogicalFunctionOp;
+import org.apache.skywalking.mqe.rt.operation.MathematicalFunctionOp;
import org.apache.skywalking.mqe.rt.type.ExpressionResult;
import org.apache.skywalking.mqe.rt.exception.IllegalExpressionException;
import org.apache.skywalking.mqe.rt.type.ExpressionResultType;
@@ -136,14 +137,14 @@ public abstract class MQEVisitorBase extends
MQEParserBaseVisitor<ExpressionResu
}
@Override
- public ExpressionResult visitFunction0OP(MQEParser.Function0OPContext ctx)
{
- int opType = ctx.function0().getStart().getType();
+ public ExpressionResult
visitMathematicalOperator0OP(MQEParser.MathematicalOperator0OPContext ctx) {
+ int opType = ctx.mathematical_operator0().getStart().getType();
ExpressionResult expResult = visit(ctx.expression());
if (StringUtil.isNotEmpty(expResult.getError())) {
return expResult;
}
try {
- return FunctionOp.doFunction0Op(expResult, opType);
+ return MathematicalFunctionOp.doFunction0Op(expResult, opType);
} catch (IllegalExpressionException e) {
ExpressionResult result = new ExpressionResult();
result.setType(ExpressionResultType.UNKNOWN);
@@ -153,14 +154,14 @@ public abstract class MQEVisitorBase extends
MQEParserBaseVisitor<ExpressionResu
}
@Override
- public ExpressionResult visitFunction1OP(MQEParser.Function1OPContext ctx)
{
- int opType = ctx.function1().getStart().getType();
+ public ExpressionResult
visitMathematicalOperator1OP(MQEParser.MathematicalOperator1OPContext ctx) {
+ int opType = ctx.mathematical_operator1().getStart().getType();
ExpressionResult expResult = visit(ctx.expression());
if (StringUtil.isNotEmpty(expResult.getError())) {
return expResult;
}
try {
- return FunctionOp.doFunction1Op(expResult, opType,
Integer.parseInt(ctx.parameter().INTEGER().getText()));
+ return MathematicalFunctionOp.doFunction1Op(expResult, opType,
Integer.parseInt(ctx.parameter().INTEGER().getText()));
} catch (IllegalExpressionException e) {
ExpressionResult result = new ExpressionResult();
result.setType(ExpressionResultType.UNKNOWN);
@@ -204,6 +205,19 @@ public abstract class MQEVisitorBase extends
MQEParserBaseVisitor<ExpressionResu
return result;
}
+ @Override
+ public ExpressionResult
visitLogicalOperatorOP(MQEParser.LogicalOperatorOPContext ctx) {
+ int opType = ctx.logical_operator().getStart().getType();
+ try {
+ return LogicalFunctionOp.doOP(opType, ctx.expressionList(), this);
+ } catch (IllegalExpressionException e) {
+ ExpressionResult result = new ExpressionResult();
+ result.setType(ExpressionResultType.UNKNOWN);
+ result.setError(e.getMessage());
+ return result;
+ }
+ }
+
@Override
public abstract ExpressionResult visitMetric(MQEParser.MetricContext ctx);
}
diff --git
a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/LogicalFunctionOp.java
b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/LogicalFunctionOp.java
new file mode 100644
index 0000000000..4bb2bdc36b
--- /dev/null
+++
b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/LogicalFunctionOp.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.mqe.rt.operation;
+
+import org.apache.skywalking.mqe.rt.exception.IllegalExpressionException;
+import org.apache.skywalking.mqe.rt.grammar.MQEParser;
+import org.apache.skywalking.mqe.rt.grammar.MQEParserBaseVisitor;
+import org.apache.skywalking.mqe.rt.type.ExpressionResult;
+import org.apache.skywalking.oap.server.library.util.CollectionUtils;
+
+public class LogicalFunctionOp {
+
+ public static ExpressionResult doOP(int opType,
MQEParser.ExpressionListContext expressionListContext,
+
MQEParserBaseVisitor<ExpressionResult> visitor) throws
IllegalExpressionException {
+ switch (opType) {
+ case MQEParser.VIEW_AS_SEQ:
+ return viewAsSeq(expressionListContext, visitor);
+ }
+
+ throw new IllegalExpressionException("Unsupported function.");
+ }
+
+ private static ExpressionResult viewAsSeq(MQEParser.ExpressionListContext
expressionListContext,
+
MQEParserBaseVisitor<ExpressionResult> visitor) {
+ ExpressionResult firstResult = null;
+ for (MQEParser.ExpressionContext expContext :
expressionListContext.expression()) {
+ final ExpressionResult result = visitor.visit(expContext);
+ if (firstResult == null) {
+ firstResult = result;
+ }
+ if (result == null ||
CollectionUtils.isEmpty(result.getResults())) {
+ continue;
+ }
+ final boolean isNotEmptyValue = result.getResults().stream()
+ .filter(s -> s != null &&
CollectionUtils.isNotEmpty(s.getValues()))
+ .flatMap(s -> s.getValues().stream()).anyMatch(s ->
!s.isEmptyValue());
+ if (isNotEmptyValue) {
+ return result;
+ }
+ }
+ return firstResult;
+ }
+
+}
diff --git
a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/FunctionOp.java
b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/MathematicalFunctionOp.java
similarity index 87%
rename from
oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/FunctionOp.java
rename to
oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/MathematicalFunctionOp.java
index 8e033a27fd..12e28a83d2 100644
---
a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/FunctionOp.java
+++
b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/MathematicalFunctionOp.java
@@ -25,16 +25,16 @@ import
org.apache.skywalking.mqe.rt.exception.IllegalExpressionException;
import org.apache.skywalking.mqe.rt.grammar.MQEParser;
import org.apache.skywalking.mqe.rt.type.ExpressionResult;
-public class FunctionOp {
+public class MathematicalFunctionOp {
public static ExpressionResult doFunction0Op(ExpressionResult expResult,
int opType) throws
IllegalExpressionException {
switch (opType) {
case MQEParser.ABS:
- return FunctionOp.transResult(expResult, Math::abs);
+ return MathematicalFunctionOp.transResult(expResult,
Math::abs);
case MQEParser.CEIL:
- return FunctionOp.transResult(expResult, Math::ceil);
+ return MathematicalFunctionOp.transResult(expResult,
Math::ceil);
case MQEParser.FLOOR:
- return FunctionOp.transResult(expResult, Math::floor);
+ return MathematicalFunctionOp.transResult(expResult,
Math::floor);
}
throw new IllegalExpressionException("Unsupported function.");
@@ -45,7 +45,7 @@ public class FunctionOp {
int scale) throws
IllegalExpressionException {
switch (opType) {
case MQEParser.ROUND:
- return FunctionOp.transResult(expResult, aDouble -> {
+ return MathematicalFunctionOp.transResult(expResult, aDouble
-> {
BigDecimal bd = BigDecimal.valueOf(aDouble);
return bd.setScale(scale,
RoundingMode.HALF_UP).doubleValue();
});
diff --git
a/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/LogicalFunctionOpTest.java
b/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/LogicalFunctionOpTest.java
new file mode 100644
index 0000000000..0b3fcea906
--- /dev/null
+++
b/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/LogicalFunctionOpTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.library.mqe.rt;
+
+import org.apache.skywalking.mqe.rt.grammar.MQEParser;
+import org.apache.skywalking.mqe.rt.grammar.MQEParserBaseVisitor;
+import org.apache.skywalking.mqe.rt.operation.LogicalFunctionOp;
+import org.apache.skywalking.mqe.rt.type.ExpressionResult;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@ExtendWith(MockitoExtension.class)
+public class LogicalFunctionOpTest {
+ private final MockData mockData = new MockData();
+
+ @Test
+ public void viewAsSeqTest() throws Exception {
+ MQEParser.ExpressionListContext expressions =
Mockito.mock(MQEParser.ExpressionListContext.class);
+ MQEParser.ExpressionContext emptyExpression =
Mockito.mock(MQEParser.ExpressionContext.class);
+ MQEParser.ExpressionContext notEmptyExpression =
Mockito.mock(MQEParser.ExpressionContext.class);
+
Mockito.when(expressions.expression()).thenReturn(Arrays.asList(emptyExpression,
notEmptyExpression));
+ final MQEParserBaseVisitor<ExpressionResult> visitor =
Mockito.mock(MQEParserBaseVisitor.class);
+ final ExpressionResult emptyResult =
mockData.newSeriesNoLabeledResult(0, 0);
+ Mockito.when(visitor.visit(emptyExpression)).thenReturn(emptyResult);
+ final ExpressionResult notEmptyResult =
mockData.newSeriesNoLabeledResult(100, 200);
+
Mockito.when(visitor.visit(notEmptyExpression)).thenReturn(notEmptyResult);
+
+ ExpressionResult result;
+ result = LogicalFunctionOp.doOP(MQEParser.VIEW_AS_SEQ, expressions,
visitor);
+ assertEquals(notEmptyResult, result);
+
+
Mockito.when(expressions.expression()).thenReturn(Arrays.asList(emptyExpression,
emptyExpression));
+ result = LogicalFunctionOp.doOP(MQEParser.VIEW_AS_SEQ, expressions,
visitor);
+ assertEquals(emptyResult, result);
+ }
+
+}
diff --git
a/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/FunctionOpTest.java
b/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/MathematicalFunctionOpTest.java
similarity index 89%
rename from
oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/FunctionOpTest.java
rename to
oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/MathematicalFunctionOpTest.java
index ebd0dae476..e5221a9f55 100644
---
a/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/FunctionOpTest.java
+++
b/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/MathematicalFunctionOpTest.java
@@ -19,20 +19,20 @@
package org.apache.skywalking.library.mqe.rt;
import org.apache.skywalking.mqe.rt.grammar.MQEParser;
-import org.apache.skywalking.mqe.rt.operation.FunctionOp;
+import org.apache.skywalking.mqe.rt.operation.MathematicalFunctionOp;
import org.apache.skywalking.mqe.rt.type.ExpressionResult;
import org.apache.skywalking.mqe.rt.type.ExpressionResultType;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
-public class FunctionOpTest {
+public class MathematicalFunctionOpTest {
private final MockData mockData = new MockData();
//ABS/CEIL/FLOOR/ROUND... are the same logic and tested in here, the
others only test ABS is enough.
@Test
public void seriesNoLabeledTest() throws Exception {
- ExpressionResult abs = FunctionOp.doFunction0Op(
+ ExpressionResult abs = MathematicalFunctionOp.doFunction0Op(
mockData.newSeriesNoLabeledResult(-100.111, -300), MQEParser.ABS);
assertEquals(ExpressionResultType.TIME_SERIES_VALUES, abs.getType());
assertEquals("100",
abs.getResults().get(0).getValues().get(0).getId());
@@ -40,7 +40,7 @@ public class FunctionOpTest {
assertEquals("300",
abs.getResults().get(0).getValues().get(1).getId());
assertEquals(300,
abs.getResults().get(0).getValues().get(1).getDoubleValue());
- ExpressionResult ceil = FunctionOp.doFunction0Op(
+ ExpressionResult ceil = MathematicalFunctionOp.doFunction0Op(
mockData.newSeriesNoLabeledResult(100.111, 300.2), MQEParser.CEIL);
assertEquals(ExpressionResultType.TIME_SERIES_VALUES, ceil.getType());
assertEquals("100",
ceil.getResults().get(0).getValues().get(0).getId());
@@ -48,7 +48,7 @@ public class FunctionOpTest {
assertEquals("300",
ceil.getResults().get(0).getValues().get(1).getId());
assertEquals(301,
ceil.getResults().get(0).getValues().get(1).getDoubleValue());
- ExpressionResult floor = FunctionOp.doFunction0Op(
+ ExpressionResult floor = MathematicalFunctionOp.doFunction0Op(
mockData.newSeriesNoLabeledResult(100.111, 300.2),
MQEParser.FLOOR);
assertEquals(ExpressionResultType.TIME_SERIES_VALUES, ceil.getType());
assertEquals("100",
floor.getResults().get(0).getValues().get(0).getId());
@@ -57,7 +57,7 @@ public class FunctionOpTest {
assertEquals(300,
floor.getResults().get(0).getValues().get(1).getDoubleValue());
MQEParser.ParameterContext parameterContext = new
MQEParser.ParameterContext(null, 0);
- ExpressionResult round = FunctionOp.doFunction1Op(
+ ExpressionResult round = MathematicalFunctionOp.doFunction1Op(
mockData.newSeriesNoLabeledResult(100.111, 300.222),
MQEParser.ROUND, 2);
assertEquals(ExpressionResultType.TIME_SERIES_VALUES, ceil.getType());
assertEquals("100",
round.getResults().get(0).getValues().get(0).getId());
@@ -68,7 +68,7 @@ public class FunctionOpTest {
@Test
public void seriesLabeledTest() throws Exception {
- ExpressionResult abs = FunctionOp.doFunction0Op(
+ ExpressionResult abs = MathematicalFunctionOp.doFunction0Op(
mockData.newSeriesLabeledResult(-100.111, -300, -101.333,
-301.666), MQEParser.ABS);
assertEquals(ExpressionResultType.TIME_SERIES_VALUES, abs.getType());
//label=1
@@ -87,7 +87,7 @@ public class FunctionOpTest {
@Test
public void listTest() throws Exception {
- ExpressionResult abs =
FunctionOp.doFunction0Op(mockData.newListResult(-100.111, -300), MQEParser.ABS);
+ ExpressionResult abs =
MathematicalFunctionOp.doFunction0Op(mockData.newListResult(-100.111, -300),
MQEParser.ABS);
assertEquals(ExpressionResultType.SORTED_LIST, abs.getType());
assertEquals("service_A",
abs.getResults().get(0).getValues().get(0).getId());
assertEquals(100.111,
abs.getResults().get(0).getValues().get(0).getDoubleValue());
diff --git
a/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/MockData.java
b/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/MockData.java
index a09e01c918..b24385cec3 100644
---
a/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/MockData.java
+++
b/oap-server/mqe-rt/src/test/java/org/apache/skywalking/library/mqe/rt/MockData.java
@@ -113,6 +113,7 @@ public class MockData {
MQEValue mqeValue = new MQEValue();
mqeValue.setId(id);
mqeValue.setDoubleValue(value);
+ mqeValue.setEmptyValue(value == 0);
return mqeValue;
}
diff --git a/test/e2e-v2/cases/mqe/expected/viewAsSeq-OP.yml
b/test/e2e-v2/cases/mqe/expected/viewAsSeq-OP.yml
new file mode 100644
index 0000000000..a4474f13e8
--- /dev/null
+++ b/test/e2e-v2/cases/mqe/expected/viewAsSeq-OP.yml
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF 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
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+type: TIME_SERIES_VALUES
+results:
+{{- contains .results }}
+ - metric:
+ labels: []
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ value: {{ .value }}
+ traceid: null
+ - id: {{ notEmpty .id }}
+ value: null
+ traceid: null
+ {{- end}}
+{{- end}}
+error: null
diff --git a/test/e2e-v2/cases/mqe/mqe-cases.yaml
b/test/e2e-v2/cases/mqe/mqe-cases.yaml
index c3f0f3d7ed..77d2356173 100644
--- a/test/e2e-v2/cases/mqe/mqe-cases.yaml
+++ b/test/e2e-v2/cases/mqe/mqe-cases.yaml
@@ -58,4 +58,8 @@ cases:
- query: swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression="aggregate_labels(service_percentile,max)"
--service-name=e2e-service-provider
expected: expected/aggregateLabels-OP.yml
- query: swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression="aggregate_labels(service_percentile,min)"
--service-name=e2e-service-provider
- expected: expected/aggregateLabels-OP.yml
\ No newline at end of file
+ expected: expected/aggregateLabels-OP.yml
+
+ # viewAsSeq-OP
+ - query: swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression="view_as_seq(mq_service_consume_sla,service_sla)"
--service-name=e2e-service-provider
+ expected: expected/viewAsSeq-OP.yml
\ No newline at end of file