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 a8cf4fb4b6 Support reduce aggregate function in MQE.(#11031) (#11036)
a8cf4fb4b6 is described below
commit a8cf4fb4b65b6ae97bc977eba8b21912d4d34f96
Author: weixiang1862 <[email protected]>
AuthorDate: Wed Jul 5 20:24:02 2023 +0800
Support reduce aggregate function in MQE.(#11031) (#11036)
---
docs/en/api/metrics-query-expression.md | 25 +++++++
docs/en/changes/changes.md | 1 +
.../apache/skywalking/mqe/rt/grammar/MQELexer.g4 | 3 +
.../apache/skywalking/mqe/rt/grammar/MQEParser.g4 | 7 ++
.../oap/query/graphql/mqe/rt/MQEVisitor.java | 24 ++++++
.../mqe/rt/operation/AggregateLabelsOp.java | 87 ++++++++++++++++++++++
.../aggregatelabels/AggregateLabelsFunc.java | 25 +++++++
.../AggregateLabelsFuncFactory.java | 23 ++++++
.../aggregatelabels/AvgAggregateLabelsFunc.java | 49 ++++++++++++
.../aggregatelabels/MaxAggregateLabelsFunc.java | 44 +++++++++++
.../aggregatelabels/MinAggregateLabelsFunc.java | 44 +++++++++++
.../aggregatelabels/SumAggregateLabelsFunc.java | 42 +++++++++++
.../query/graphql/mqe/AggregateLabelsOpTest.java | 55 ++++++++++++++
.../cases/mqe/expected/aggregateLabels-OP.yml | 31 ++++++++
test/e2e-v2/cases/mqe/mqe-cases.yaml | 10 +++
15 files changed, 470 insertions(+)
diff --git a/docs/en/api/metrics-query-expression.md
b/docs/en/api/metrics-query-expression.md
index 847bd061a9..8eec5020f9 100644
--- a/docs/en/api/metrics-query-expression.md
+++ b/docs/en/api/metrics-query-expression.md
@@ -178,3 +178,28 @@ relabel(service_percentile{label='0,1,2,3,4'},
label='P50,P75,P90,P95,P99')
### Result Type
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`.
+
+Expression:
+```text
+aggregate_labels(Expression, parameter)
+```
+
+| parameter | Definition |
ExpressionResultType |
+|-----------|-----------------------------------------------------|----------------------|
+| 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 |
+
+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):
+
+```text
+aggregate_labels(total_commands_rate, SUM)
+```
+
+### Result Type
+The ExpressionResultType of the aggregateLabels operation is
TIME_SERIES_VALUES.
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index 81da76f9d0..722834a4a2 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -36,6 +36,7 @@
* Accept `length=4000` parameter value of the event. It was 2000.
* Tolerate parameter value in illegal JSON format.
* Update BanyanDB Java Client to 0.4.0
+* Support aggregate `Labeled Value Metrics` in MQE.
#### UI
diff --git
a/oap-server/server-query-plugin/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
b/oap-server/server-query-plugin/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
index ee7396498e..221f57a1cf 100644
---
a/oap-server/server-query-plugin/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
+++
b/oap-server/server-query-plugin/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
@@ -70,6 +70,9 @@ RELABELS: 'relabels';
ASC options { caseInsensitive=true; }: 'asc';
DES options { caseInsensitive=true; }: 'des';
+// AGGREGATE_LABELS
+AGGREGATE_LABELS: 'aggregate_labels';
+
// Literals
INTEGER: Digit+;
DECIMAL: Digit+ DOT Digit+;
diff --git
a/oap-server/server-query-plugin/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
b/oap-server/server-query-plugin/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
index 77892763fe..876a81d0d6 100644
---
a/oap-server/server-query-plugin/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
+++
b/oap-server/server-query-plugin/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
@@ -32,6 +32,7 @@ expression
| function1 L_PAREN expression COMMA parameter R_PAREN #function1OP
| 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
;
expressionNode: metric| scalar;
@@ -68,3 +69,9 @@ relabels: RELABELS;
parameter: INTEGER;
order: ASC | DES;
+
+aggregateLabels:
+ AGGREGATE_LABELS;
+
+aggregateLabelsFunc:
+ AVG | SUM | MAX | MIN;
\ No newline at end of file
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
index 0b62b9e822..b732d03db6 100644
---
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import
org.apache.skywalking.oap.query.graphql.mqe.rt.exception.IllegalExpressionException;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.operation.AggregateLabelsOp;
import org.apache.skywalking.oap.query.graphql.mqe.rt.operation.AggregationOp;
import org.apache.skywalking.oap.query.graphql.resolver.MetricsQuery;
import org.apache.skywalking.oap.query.graphql.resolver.RecordsQuery;
@@ -150,6 +151,29 @@ public class MQEVisitor extends
MQEParserBaseVisitor<ExpressionResult> {
}
}
+ @Override
+ public ExpressionResult visitAggregateLabelsOp(final
MQEParser.AggregateLabelsOpContext ctx) {
+ int funcType = ctx.aggregateLabelsFunc().getStart().getType();
+ ExpressionResult expResult = visit(ctx.expression());
+ if (StringUtil.isNotEmpty(expResult.getError())) {
+ return expResult;
+ }
+
+ if (!expResult.isLabeledResult()) {
+ expResult.setError("The result of expression [" +
ctx.expression().getText() + "] is not a labeled result.");
+ return expResult;
+ }
+
+ try {
+ return AggregateLabelsOp.doAggregateLabelsOp(expResult, funcType);
+ } catch (IllegalExpressionException e) {
+ ExpressionResult result = new ExpressionResult();
+ result.setType(ExpressionResultType.UNKNOWN);
+ result.setError(e.getMessage());
+ return result;
+ }
+ }
+
@Override
public ExpressionResult visitFunction0OP(MQEParser.Function0OPContext ctx)
{
int opType = ctx.function0().getStart().getType();
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/AggregateLabelsOp.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/AggregateLabelsOp.java
new file mode 100644
index 0000000000..759f2ba8ad
--- /dev/null
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/AggregateLabelsOp.java
@@ -0,0 +1,87 @@
+/*
+ * 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.oap.query.graphql.mqe.rt.operation;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.skywalking.mqe.rt.grammar.MQEParser;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.exception.IllegalExpressionException;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.operation.aggregatelabels.AggregateLabelsFunc;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.operation.aggregatelabels.AggregateLabelsFuncFactory;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.operation.aggregatelabels.AvgAggregateLabelsFunc;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.operation.aggregatelabels.MaxAggregateLabelsFunc;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.operation.aggregatelabels.MinAggregateLabelsFunc;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.operation.aggregatelabels.SumAggregateLabelsFunc;
+import org.apache.skywalking.oap.query.graphql.type.mql.ExpressionResult;
+import org.apache.skywalking.oap.query.graphql.type.mql.MQEValue;
+import org.apache.skywalking.oap.query.graphql.type.mql.MQEValues;
+import org.apache.skywalking.oap.query.graphql.type.mql.Metadata;
+
+public class AggregateLabelsOp {
+
+ public static ExpressionResult doAggregateLabelsOp(ExpressionResult result,
+ int funcType) throws
IllegalExpressionException {
+ switch (funcType) {
+ case MQEParser.AVG:
+ return aggregateLabeledValueResult(result,
AvgAggregateLabelsFunc::new);
+ case MQEParser.SUM:
+ return aggregateLabeledValueResult(result,
SumAggregateLabelsFunc::new);
+ case MQEParser.MAX:
+ return aggregateLabeledValueResult(result,
MaxAggregateLabelsFunc::new);
+ case MQEParser.MIN:
+ return aggregateLabeledValueResult(result,
MinAggregateLabelsFunc::new);
+ default:
+ throw new IllegalExpressionException("Unsupported
aggregateLabels function.");
+ }
+ }
+
+ private static ExpressionResult
aggregateLabeledValueResult(ExpressionResult expResult,
+
AggregateLabelsFuncFactory factory) {
+ List<MQEValues> results = expResult.getResults();
+
+ List<MQEValue> combineTo = results.get(0).getValues();
+ for (int i = 0; i < combineTo.size(); i++) {
+ AggregateLabelsFunc aggregateLabelsFunc =
factory.getAggregateLabelsFunc();
+ for (MQEValues result : results) {
+ MQEValue toCombine = result.getValues().get(i);
+ if (!toCombine.isEmptyValue()) {
+ aggregateLabelsFunc.combine(toCombine.getDoubleValue());
+ }
+ }
+
+ MQEValue mqeValue = combineTo.get(i);
+ mqeValue.setTraceID(null);
+ mqeValue.setEmptyValue(true);
+ mqeValue.setDoubleValue(0);
+
+ Double result = aggregateLabelsFunc.getResult();
+ if (result != null) {
+ mqeValue.setEmptyValue(false);
+ mqeValue.setDoubleValue(result);
+ }
+ }
+
+ MQEValues mqeValues = new MQEValues();
+ mqeValues.setMetric(new Metadata());
+ mqeValues.setValues(combineTo);
+ expResult.setResults(Collections.singletonList(mqeValues));
+ expResult.setLabeledResult(false);
+ return expResult;
+ }
+}
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AggregateLabelsFunc.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AggregateLabelsFunc.java
new file mode 100644
index 0000000000..a5be384cae
--- /dev/null
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AggregateLabelsFunc.java
@@ -0,0 +1,25 @@
+/*
+ * 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.oap.query.graphql.mqe.rt.operation.aggregatelabels;
+
+public interface AggregateLabelsFunc {
+ void combine(Double value);
+
+ Double getResult();
+}
\ No newline at end of file
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AggregateLabelsFuncFactory.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AggregateLabelsFuncFactory.java
new file mode 100644
index 0000000000..861be9067b
--- /dev/null
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AggregateLabelsFuncFactory.java
@@ -0,0 +1,23 @@
+/*
+ * 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.oap.query.graphql.mqe.rt.operation.aggregatelabels;
+
+public interface AggregateLabelsFuncFactory {
+ AggregateLabelsFunc getAggregateLabelsFunc();
+}
\ No newline at end of file
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AvgAggregateLabelsFunc.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AvgAggregateLabelsFunc.java
new file mode 100644
index 0000000000..c9775d307f
--- /dev/null
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/AvgAggregateLabelsFunc.java
@@ -0,0 +1,49 @@
+/*
+ * 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.oap.query.graphql.mqe.rt.operation.aggregatelabels;
+
+public class AvgAggregateLabelsFunc implements AggregateLabelsFunc {
+
+ private Double sum;
+ private Integer count = 0;
+
+ @Override
+ public void combine(final Double value) {
+ if (value == null) {
+ return;
+ }
+
+ if (sum == null) {
+ sum = value;
+ } else {
+ sum = sum + value;
+ }
+
+ count++;
+ }
+
+ @Override
+ public Double getResult() {
+ if (sum == null) {
+ return null;
+ }
+
+ return sum / count;
+ }
+}
\ No newline at end of file
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/MaxAggregateLabelsFunc.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/MaxAggregateLabelsFunc.java
new file mode 100644
index 0000000000..7da0e2e39e
--- /dev/null
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/MaxAggregateLabelsFunc.java
@@ -0,0 +1,44 @@
+/*
+ * 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.oap.query.graphql.mqe.rt.operation.aggregatelabels;
+
+public class MaxAggregateLabelsFunc implements AggregateLabelsFunc {
+
+ private Double max;
+
+ @Override
+ public void combine(final Double value) {
+ if (value == null) {
+ return;
+ }
+
+ if (max == null) {
+ max = value;
+ } else {
+ if (value > max) {
+ max = value;
+ }
+ }
+ }
+
+ @Override
+ public Double getResult() {
+ return max;
+ }
+}
\ No newline at end of file
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/MinAggregateLabelsFunc.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/MinAggregateLabelsFunc.java
new file mode 100644
index 0000000000..9fce89148f
--- /dev/null
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/MinAggregateLabelsFunc.java
@@ -0,0 +1,44 @@
+/*
+ * 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.oap.query.graphql.mqe.rt.operation.aggregatelabels;
+
+public class MinAggregateLabelsFunc implements AggregateLabelsFunc {
+
+ private Double min;
+
+ @Override
+ public void combine(final Double value) {
+ if (value == null) {
+ return;
+ }
+
+ if (min == null) {
+ min = value;
+ } else {
+ if (value < min) {
+ min = value;
+ }
+ }
+ }
+
+ @Override
+ public Double getResult() {
+ return min;
+ }
+}
\ No newline at end of file
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/SumAggregateLabelsFunc.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/SumAggregateLabelsFunc.java
new file mode 100644
index 0000000000..9951633b19
--- /dev/null
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/aggregatelabels/SumAggregateLabelsFunc.java
@@ -0,0 +1,42 @@
+/*
+ * 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.oap.query.graphql.mqe.rt.operation.aggregatelabels;
+
+public class SumAggregateLabelsFunc implements AggregateLabelsFunc {
+
+ private Double sum;
+
+ @Override
+ public void combine(final Double value) {
+ if (value == null) {
+ return;
+ }
+
+ if (sum == null) {
+ sum = value;
+ } else {
+ sum = sum + value;
+ }
+ }
+
+ @Override
+ public Double getResult() {
+ return sum;
+ }
+}
\ No newline at end of file
diff --git
a/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/AggregateLabelsOpTest.java
b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/AggregateLabelsOpTest.java
new file mode 100644
index 0000000000..c288328a1e
--- /dev/null
+++
b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/AggregateLabelsOpTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.oap.query.graphql.mqe;
+
+import org.apache.skywalking.mqe.rt.grammar.MQEParser;
+import
org.apache.skywalking.oap.query.graphql.mqe.rt.operation.AggregateLabelsOp;
+import org.apache.skywalking.oap.query.graphql.type.mql.ExpressionResult;
+import org.apache.skywalking.oap.query.graphql.type.mql.ExpressionResultType;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class AggregateLabelsOpTest {
+
+ private final MockData mockData = new MockData();
+
+ @Test
+ public void seriesLabeledTest() throws Exception {
+ ExpressionResult avgReduce =
AggregateLabelsOp.doAggregateLabelsOp(mockData.newSeriesLabeledResult(),
MQEParser.AVG);
+ assertEquals(ExpressionResultType.TIME_SERIES_VALUES,
avgReduce.getType());
+ assertEquals((100f + 101f) / 2,
avgReduce.getResults().get(0).getValues().get(0).getDoubleValue());
+ assertEquals((300f + 301f) / 2,
avgReduce.getResults().get(0).getValues().get(1).getDoubleValue());
+
+ ExpressionResult sumReduce =
AggregateLabelsOp.doAggregateLabelsOp(mockData.newSeriesLabeledResult(),
MQEParser.SUM);
+ assertEquals(ExpressionResultType.TIME_SERIES_VALUES,
sumReduce.getType());
+ assertEquals(100f + 101f,
sumReduce.getResults().get(0).getValues().get(0).getDoubleValue());
+ assertEquals(300f + 301f,
sumReduce.getResults().get(0).getValues().get(1).getDoubleValue());
+
+ ExpressionResult minReduce =
AggregateLabelsOp.doAggregateLabelsOp(mockData.newSeriesLabeledResult(),
MQEParser.MIN);
+ assertEquals(ExpressionResultType.TIME_SERIES_VALUES,
minReduce.getType());
+ assertEquals(100f,
minReduce.getResults().get(0).getValues().get(0).getDoubleValue());
+ assertEquals(300f,
minReduce.getResults().get(0).getValues().get(1).getDoubleValue());
+
+ ExpressionResult maxReduce =
AggregateLabelsOp.doAggregateLabelsOp(mockData.newSeriesLabeledResult(),
MQEParser.MAX);
+ assertEquals(ExpressionResultType.TIME_SERIES_VALUES,
maxReduce.getType());
+ assertEquals(101f,
maxReduce.getResults().get(0).getValues().get(0).getDoubleValue());
+ assertEquals(301f,
maxReduce.getResults().get(0).getValues().get(1).getDoubleValue());
+ }
+}
diff --git a/test/e2e-v2/cases/mqe/expected/aggregateLabels-OP.yml
b/test/e2e-v2/cases/mqe/expected/aggregateLabels-OP.yml
new file mode 100644
index 0000000000..c4bbbafa3b
--- /dev/null
+++ b/test/e2e-v2/cases/mqe/expected/aggregateLabels-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
\ No newline at end of file
diff --git a/test/e2e-v2/cases/mqe/mqe-cases.yaml
b/test/e2e-v2/cases/mqe/mqe-cases.yaml
index fcaf79e36f..466bde52a4 100644
--- a/test/e2e-v2/cases/mqe/mqe-cases.yaml
+++ b/test/e2e-v2/cases/mqe/mqe-cases.yaml
@@ -49,3 +49,13 @@ cases:
expected: expected/relabels-binary-OP.yml
- query: swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression="relabels(service_percentile{label='0,1,2'}/service_percentile{label='0,1,2'},label='P50,P75,P90')"
--service-name=e2e-service-provider
expected: expected/relabels-binary-OP.yml
+
+ # aggregateLabels-OP
+ - query: swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression="aggregate_labels(service_percentile,avg)"
--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,sum)"
--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,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