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

Reply via email to