From feb3ca2b6d86cc01a4feba41b28b7ff20a15e499 Mon Sep 17 00:00:00 2001 From: Wan Kai Date: Tue, 13 Jun 2023 17:58:15 +0800 Subject: [PATCH] Add UT and E2E for MQE. (#10920) --- .github/workflows/skywalking.yaml | 3 + .../oap/query/graphql/mqe/rt/MQEVisitor.java | 2 +- .../graphql/mqe/rt/operation/FunctionOp.java | 4 +- .../query/graphql/mqe/AggregationOpTest.java | 122 +++++ .../oap/query/graphql/mqe/BinaryOpTest.java | 145 ++++++ .../oap/query/graphql/mqe/FunctionOpTest.java | 97 ++++ .../oap/query/graphql/mqe/MockData.java | 124 ++++++ .../general/general-instance.json | 420 ++++++++++-------- test/e2e-v2/cases/mqe/docker-compose.yml | 49 ++ test/e2e-v2/cases/mqe/e2e.yaml | 47 ++ .../cases/mqe/expected/aggregation-OP.yml | 24 + test/e2e-v2/cases/mqe/expected/binary-OP.yml | 31 ++ test/e2e-v2/cases/mqe/expected/func-OP.yml | 31 ++ test/e2e-v2/cases/mqe/expected/no-OP.yml | 31 ++ .../e2e-v2/cases/mqe/expected/relabels-OP.yml | 59 +++ .../cases/mqe/expected/relabels-binary-OP.yml | 59 +++ .../cases/mqe/expected/topN-OP-instance.yml | 24 + .../cases/mqe/expected/topN-OP-service.yml | 27 ++ test/e2e-v2/cases/mqe/mqe-cases.yaml | 51 +++ 19 files changed, 1161 insertions(+), 189 deletions(-) create mode 100644 oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/AggregationOpTest.java create mode 100644 oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/BinaryOpTest.java create mode 100644 oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/FunctionOpTest.java create mode 100644 oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/MockData.java create mode 100644 test/e2e-v2/cases/mqe/docker-compose.yml create mode 100644 test/e2e-v2/cases/mqe/e2e.yaml create mode 100644 test/e2e-v2/cases/mqe/expected/aggregation-OP.yml create mode 100644 test/e2e-v2/cases/mqe/expected/binary-OP.yml create mode 100644 test/e2e-v2/cases/mqe/expected/func-OP.yml create mode 100644 test/e2e-v2/cases/mqe/expected/no-OP.yml create mode 100644 test/e2e-v2/cases/mqe/expected/relabels-OP.yml create mode 100644 test/e2e-v2/cases/mqe/expected/relabels-binary-OP.yml create mode 100644 test/e2e-v2/cases/mqe/expected/topN-OP-instance.yml create mode 100644 test/e2e-v2/cases/mqe/expected/topN-OP-service.yml create mode 100644 test/e2e-v2/cases/mqe/mqe-cases.yaml diff --git a/.github/workflows/skywalking.yaml b/.github/workflows/skywalking.yaml index c369386a83..2ab10625cd 100644 --- a/.github/workflows/skywalking.yaml +++ b/.github/workflows/skywalking.yaml @@ -700,6 +700,9 @@ jobs: config: test/e2e-v2/cases/elasticsearch/e2e.yaml - name: RabbitMQ config: test/e2e-v2/cases/rabbitmq/e2e.yaml + - name: MQE Service + config: test/e2e-v2/cases/mqe/e2e.yaml + steps: - uses: actions/checkout@v3 with: 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 9ae57e0441..0b62b9e822 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 @@ -175,7 +175,7 @@ public class MQEVisitor extends MQEParserBaseVisitor { return expResult; } try { - return doFunction1Op(expResult, opType, ctx.parameter()); + return doFunction1Op(expResult, opType, Integer.parseInt(ctx.parameter().INTEGER().getText())); } catch (IllegalExpressionException e) { ExpressionResult result = new ExpressionResult(); result.setType(ExpressionResultType.UNKNOWN); diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/FunctionOp.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/FunctionOp.java index d60380bd7a..da5f5953e6 100644 --- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/FunctionOp.java +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/operation/FunctionOp.java @@ -42,12 +42,12 @@ public class FunctionOp { public static ExpressionResult doFunction1Op(ExpressionResult expResult, int opType, - MQEParser.ParameterContext params) throws IllegalExpressionException { + int scale) throws IllegalExpressionException { switch (opType) { case MQEParser.ROUND: return FunctionOp.transResult(expResult, aDouble -> { BigDecimal bd = BigDecimal.valueOf(aDouble); - return bd.setScale(Integer.parseInt(params.INTEGER().getText()), RoundingMode.HALF_UP).doubleValue(); + return bd.setScale(scale, RoundingMode.HALF_UP).doubleValue(); }); } diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/AggregationOpTest.java b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/AggregationOpTest.java new file mode 100644 index 0000000000..1c271f5cc4 --- /dev/null +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/AggregationOpTest.java @@ -0,0 +1,122 @@ +/* + * 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.AggregationOp; +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; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class AggregationOpTest { + private final MockData mockData = new MockData(); + + @Test + public void seriesNoLabeledTest() throws Exception { + ExpressionResult avg = AggregationOp.doAggregationOp(mockData.newSeriesNoLabeledResult(), MQEParser.AVG); + assertEquals(ExpressionResultType.SINGLE_VALUE, avg.getType()); + assertNull(avg.getResults().get(0).getValues().get(0).getId()); + assertEquals(200, avg.getResults().get(0).getValues().get(0).getDoubleValue()); + + ExpressionResult count = AggregationOp.doAggregationOp(mockData.newSeriesNoLabeledResult(), MQEParser.COUNT); + assertEquals(ExpressionResultType.SINGLE_VALUE, count.getType()); + assertNull(count.getResults().get(0).getValues().get(0).getId()); + assertEquals(2, count.getResults().get(0).getValues().get(0).getDoubleValue()); + + ExpressionResult sum = AggregationOp.doAggregationOp(mockData.newSeriesNoLabeledResult(), MQEParser.SUM); + assertEquals(ExpressionResultType.SINGLE_VALUE, sum.getType()); + assertNull(sum.getResults().get(0).getValues().get(0).getId()); + assertEquals(400, sum.getResults().get(0).getValues().get(0).getDoubleValue()); + + ExpressionResult latest = AggregationOp.doAggregationOp(mockData.newSeriesNoLabeledResult(), MQEParser.LATEST); + assertEquals(ExpressionResultType.SINGLE_VALUE, latest.getType()); + assertEquals("300", latest.getResults().get(0).getValues().get(0).getId()); + assertEquals(300, latest.getResults().get(0).getValues().get(0).getDoubleValue()); + + ExpressionResult max = AggregationOp.doAggregationOp(mockData.newSeriesNoLabeledResult(), MQEParser.MAX); + assertEquals(ExpressionResultType.SINGLE_VALUE, max.getType()); + assertEquals("300", max.getResults().get(0).getValues().get(0).getId()); + assertEquals(300, max.getResults().get(0).getValues().get(0).getDoubleValue()); + + ExpressionResult min = AggregationOp.doAggregationOp(mockData.newSeriesNoLabeledResult(), MQEParser.MIN); + assertEquals(ExpressionResultType.SINGLE_VALUE, min.getType()); + assertEquals("100", min.getResults().get(0).getValues().get(0).getId()); + assertEquals(100, min.getResults().get(0).getValues().get(0).getDoubleValue()); + } + + @Test + public void seriesLabeledTest() throws Exception { + ExpressionResult avg = AggregationOp.doAggregationOp(mockData.newSeriesLabeledResult(), MQEParser.AVG); + assertEquals(ExpressionResultType.SINGLE_VALUE, avg.getType()); + //label=1 + assertNull(avg.getResults().get(0).getValues().get(0).getId()); + assertEquals(200, avg.getResults().get(0).getValues().get(0).getDoubleValue()); + //label=2 + assertNull(avg.getResults().get(1).getValues().get(0).getId()); + assertEquals(201, avg.getResults().get(1).getValues().get(0).getDoubleValue()); + + ExpressionResult count = AggregationOp.doAggregationOp(mockData.newSeriesLabeledResult(), MQEParser.COUNT); + assertEquals(ExpressionResultType.SINGLE_VALUE, avg.getType()); + //label=1 + assertNull(count.getResults().get(0).getValues().get(0).getId()); + assertEquals(2, count.getResults().get(0).getValues().get(0).getDoubleValue()); + //label=2 + assertNull(count.getResults().get(1).getValues().get(0).getId()); + assertEquals(2, count.getResults().get(1).getValues().get(0).getDoubleValue()); + + ExpressionResult sum = AggregationOp.doAggregationOp(mockData.newSeriesLabeledResult(), MQEParser.SUM); + assertEquals(ExpressionResultType.SINGLE_VALUE, avg.getType()); + //label=1 + assertNull(sum.getResults().get(0).getValues().get(0).getId()); + assertEquals(400, sum.getResults().get(0).getValues().get(0).getDoubleValue()); + //label=2 + assertNull(sum.getResults().get(1).getValues().get(0).getId()); + assertEquals(402, sum.getResults().get(1).getValues().get(0).getDoubleValue()); + + ExpressionResult latest = AggregationOp.doAggregationOp(mockData.newSeriesLabeledResult(), MQEParser.LATEST); + assertEquals(ExpressionResultType.SINGLE_VALUE, avg.getType()); + //label=1 + assertEquals("300", latest.getResults().get(0).getValues().get(0).getId()); + assertEquals(300, latest.getResults().get(0).getValues().get(0).getDoubleValue()); + //label=2 + assertEquals("300", latest.getResults().get(1).getValues().get(0).getId()); + assertEquals(301, latest.getResults().get(1).getValues().get(0).getDoubleValue()); + + ExpressionResult max = AggregationOp.doAggregationOp(mockData.newSeriesLabeledResult(), MQEParser.MAX); + assertEquals(ExpressionResultType.SINGLE_VALUE, avg.getType()); + //label=1 + assertEquals("300", max.getResults().get(0).getValues().get(0).getId()); + assertEquals(300, max.getResults().get(0).getValues().get(0).getDoubleValue()); + //label=2 + assertEquals("300", max.getResults().get(1).getValues().get(0).getId()); + assertEquals(301, max.getResults().get(1).getValues().get(0).getDoubleValue()); + + ExpressionResult min = AggregationOp.doAggregationOp(mockData.newSeriesLabeledResult(), MQEParser.MIN); + assertEquals(ExpressionResultType.SINGLE_VALUE, avg.getType()); + //label=1 + assertEquals("100", min.getResults().get(0).getValues().get(0).getId()); + assertEquals(100, min.getResults().get(0).getValues().get(0).getDoubleValue()); + //label=2 + assertEquals("100", min.getResults().get(1).getValues().get(0).getId()); + assertEquals(101, min.getResults().get(1).getValues().get(0).getDoubleValue()); + } +} diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/BinaryOpTest.java b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/BinaryOpTest.java new file mode 100644 index 0000000000..ab24aa1fc8 --- /dev/null +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/BinaryOpTest.java @@ -0,0 +1,145 @@ +/* + * 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.BinaryOp; +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 BinaryOpTest { + private final MockData mockData = new MockData(); + + //DIV/MUL/MOD/SUB... are the same logic and tested in here, the others only test ADD is enough. + @Test + public void seriesNoLabeledTest() throws Exception { + ExpressionResult add = BinaryOp.doBinaryOp( + mockData.newSeriesNoLabeledResult(), mockData.newSeriesNoLabeledResult(), MQEParser.ADD); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, add.getType()); + assertEquals("100", add.getResults().get(0).getValues().get(0).getId()); + assertEquals(200, add.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", add.getResults().get(0).getValues().get(1).getId()); + assertEquals(600, add.getResults().get(0).getValues().get(1).getDoubleValue()); + + ExpressionResult sub = BinaryOp.doBinaryOp( + mockData.newSeriesNoLabeledResult(), mockData.newSeriesNoLabeledResult(), MQEParser.SUB); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, sub.getType()); + assertEquals("100", sub.getResults().get(0).getValues().get(0).getId()); + assertEquals(0, sub.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", sub.getResults().get(0).getValues().get(1).getId()); + assertEquals(0, sub.getResults().get(0).getValues().get(1).getDoubleValue()); + + ExpressionResult mul = BinaryOp.doBinaryOp( + mockData.newSeriesNoLabeledResult(), mockData.newSeriesNoLabeledResult(), MQEParser.MUL); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, mul.getType()); + assertEquals("100", mul.getResults().get(0).getValues().get(0).getId()); + assertEquals(10000, mul.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", mul.getResults().get(0).getValues().get(1).getId()); + assertEquals(90000, mul.getResults().get(0).getValues().get(1).getDoubleValue()); + + ExpressionResult div = BinaryOp.doBinaryOp( + mockData.newSeriesNoLabeledResult(), mockData.newSeriesNoLabeledResult(), MQEParser.DIV); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, div.getType()); + assertEquals("100", div.getResults().get(0).getValues().get(0).getId()); + assertEquals(1, div.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", div.getResults().get(0).getValues().get(1).getId()); + assertEquals(1, div.getResults().get(0).getValues().get(1).getDoubleValue()); + + ExpressionResult mod = BinaryOp.doBinaryOp( + mockData.newSeriesNoLabeledResult(), mockData.newSeriesNoLabeledResult(), MQEParser.MOD); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, mod.getType()); + assertEquals("100", mod.getResults().get(0).getValues().get(0).getId()); + assertEquals(0, mod.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", mod.getResults().get(0).getValues().get(1).getId()); + assertEquals(0, mod.getResults().get(0).getValues().get(1).getDoubleValue()); + } + + @Test + public void seriesLabeledTest() throws Exception { + //seriesLabeled + seriesNoLabeled + ExpressionResult add = BinaryOp.doBinaryOp(mockData.newSeriesLabeledResult(), mockData.newSeriesNoLabeledResult(), MQEParser.ADD); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, add.getType()); + //label=1 + assertEquals("1", add.getResults().get(0).getMetric().getLabels().get(0).getValue()); + assertEquals("100", add.getResults().get(0).getValues().get(0).getId()); + assertEquals(200, add.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", add.getResults().get(0).getValues().get(1).getId()); + assertEquals(600, add.getResults().get(0).getValues().get(1).getDoubleValue()); + //label=2 + assertEquals("2", add.getResults().get(1).getMetric().getLabels().get(0).getValue()); + assertEquals("100", add.getResults().get(1).getValues().get(0).getId()); + assertEquals(201, add.getResults().get(1).getValues().get(0).getDoubleValue()); + assertEquals("300", add.getResults().get(1).getValues().get(1).getId()); + assertEquals(601, add.getResults().get(1).getValues().get(1).getDoubleValue()); + + //seriesLabeled + seriesLabeled + add = BinaryOp.doBinaryOp(mockData.newSeriesLabeledResult(), mockData.newSeriesLabeledResult(), MQEParser.ADD); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, add.getType()); + //label=1 + assertEquals("1", add.getResults().get(0).getMetric().getLabels().get(0).getValue()); + assertEquals("100", add.getResults().get(0).getValues().get(0).getId()); + assertEquals(200, add.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", add.getResults().get(0).getValues().get(1).getId()); + assertEquals(600, add.getResults().get(0).getValues().get(1).getDoubleValue()); + //label=2 + assertEquals("2", add.getResults().get(1).getMetric().getLabels().get(0).getValue()); + assertEquals("100", add.getResults().get(1).getValues().get(0).getId()); + assertEquals(202, add.getResults().get(1).getValues().get(0).getDoubleValue()); + assertEquals("300", add.getResults().get(1).getValues().get(1).getId()); + assertEquals(602, add.getResults().get(1).getValues().get(1).getDoubleValue()); + } + + @Test + public void many2OneTest() throws Exception { + //sort_list + single + ExpressionResult add = BinaryOp.doBinaryOp(mockData.newListResult(), mockData.newSingleResult(), MQEParser.ADD); + assertEquals(ExpressionResultType.SORTED_LIST, add.getType()); + assertEquals("service_A", add.getResults().get(0).getValues().get(0).getId()); + assertEquals(1100, add.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("service_B", add.getResults().get(0).getValues().get(1).getId()); + assertEquals(1300, add.getResults().get(0).getValues().get(1).getDoubleValue()); + + //seriesNoLabeled + single + add = BinaryOp.doBinaryOp(mockData.newSeriesNoLabeledResult(), mockData.newSingleResult(), MQEParser.ADD); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, add.getType()); + assertEquals("100", add.getResults().get(0).getValues().get(0).getId()); + assertEquals(1100, add.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", add.getResults().get(0).getValues().get(1).getId()); + assertEquals(1300, add.getResults().get(0).getValues().get(1).getDoubleValue()); + + //seriesLabeled + single + add = BinaryOp.doBinaryOp(mockData.newSeriesLabeledResult(), mockData.newSingleResult(), MQEParser.ADD); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, add.getType()); + //label=1 + assertEquals("1", add.getResults().get(0).getMetric().getLabels().get(0).getValue()); + assertEquals("100", add.getResults().get(0).getValues().get(0).getId()); + assertEquals(1100, add.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", add.getResults().get(0).getValues().get(1).getId()); + assertEquals(1300, add.getResults().get(0).getValues().get(1).getDoubleValue()); + //label=2 + assertEquals("2", add.getResults().get(1).getMetric().getLabels().get(0).getValue()); + assertEquals("100", add.getResults().get(1).getValues().get(0).getId()); + assertEquals(1101, add.getResults().get(1).getValues().get(0).getDoubleValue()); + assertEquals("300", add.getResults().get(1).getValues().get(1).getId()); + assertEquals(1301, add.getResults().get(1).getValues().get(1).getDoubleValue()); + } +} diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/FunctionOpTest.java b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/FunctionOpTest.java new file mode 100644 index 0000000000..57ab3367e5 --- /dev/null +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/FunctionOpTest.java @@ -0,0 +1,97 @@ +/* + * 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.FunctionOp; +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 FunctionOpTest { + 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( + mockData.newSeriesNoLabeledResult(-100.111, -300), MQEParser.ABS); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, abs.getType()); + assertEquals("100", abs.getResults().get(0).getValues().get(0).getId()); + assertEquals(100.111, abs.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", abs.getResults().get(0).getValues().get(1).getId()); + assertEquals(300, abs.getResults().get(0).getValues().get(1).getDoubleValue()); + + ExpressionResult ceil = FunctionOp.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()); + assertEquals(101, ceil.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", ceil.getResults().get(0).getValues().get(1).getId()); + assertEquals(301, ceil.getResults().get(0).getValues().get(1).getDoubleValue()); + + ExpressionResult floor = FunctionOp.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()); + assertEquals(100, floor.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", floor.getResults().get(0).getValues().get(1).getId()); + assertEquals(300, floor.getResults().get(0).getValues().get(1).getDoubleValue()); + + MQEParser.ParameterContext parameterContext = new MQEParser.ParameterContext(null, 0); + ExpressionResult round = FunctionOp.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()); + assertEquals(100.11, round.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", round.getResults().get(0).getValues().get(1).getId()); + assertEquals(300.22, round.getResults().get(0).getValues().get(1).getDoubleValue()); + } + + @Test + public void seriesLabeledTest() throws Exception { + ExpressionResult abs = FunctionOp.doFunction0Op( + mockData.newSeriesLabeledResult(-100.111, -300, -101.333, -301.666), MQEParser.ABS); + assertEquals(ExpressionResultType.TIME_SERIES_VALUES, abs.getType()); + //label=1 + assertEquals("1", abs.getResults().get(0).getMetric().getLabels().get(0).getValue()); + assertEquals("100", abs.getResults().get(0).getValues().get(0).getId()); + assertEquals(100.111, abs.getResults().get(0).getValues().get(0).getDoubleValue()); + assertEquals("300", abs.getResults().get(0).getValues().get(1).getId()); + assertEquals(300, abs.getResults().get(0).getValues().get(1).getDoubleValue()); + //label=2 + assertEquals("2", abs.getResults().get(1).getMetric().getLabels().get(0).getValue()); + assertEquals("100", abs.getResults().get(1).getValues().get(0).getId()); + assertEquals(101.333, abs.getResults().get(1).getValues().get(0).getDoubleValue()); + assertEquals("300", abs.getResults().get(1).getValues().get(1).getId()); + assertEquals(301.666, abs.getResults().get(1).getValues().get(1).getDoubleValue()); + } + + @Test + public void listTest() throws Exception { + ExpressionResult abs = FunctionOp.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()); + assertEquals("service_B", abs.getResults().get(0).getValues().get(1).getId()); + assertEquals(300, abs.getResults().get(0).getValues().get(1).getDoubleValue()); + } +} diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/MockData.java b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/MockData.java new file mode 100644 index 0000000000..578b565430 --- /dev/null +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe/MockData.java @@ -0,0 +1,124 @@ +/* + * 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.oap.query.graphql.type.mql.ExpressionResult; +import org.apache.skywalking.oap.query.graphql.type.mql.ExpressionResultType; +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; +import org.apache.skywalking.oap.server.core.query.type.KeyValue; + +public class MockData { + public ExpressionResult newSeriesNoLabeledResult() { + ExpressionResult seriesNoLabeled = new ExpressionResult(); + seriesNoLabeled.setType(ExpressionResultType.TIME_SERIES_VALUES); + MQEValues mqeValues = new MQEValues(); + mqeValues.getValues().add(newMQEValue("100", 100)); + mqeValues.getValues().add(newMQEValue("300", 300)); + seriesNoLabeled.getResults().add(mqeValues); + return seriesNoLabeled; + } + + public ExpressionResult newSeriesNoLabeledResult(double id100, double id300) { + ExpressionResult seriesNoLabeled = new ExpressionResult(); + seriesNoLabeled.setType(ExpressionResultType.TIME_SERIES_VALUES); + MQEValues mqeValues = new MQEValues(); + mqeValues.getValues().add(newMQEValue("100", id100)); + mqeValues.getValues().add(newMQEValue("300", id300)); + seriesNoLabeled.getResults().add(mqeValues); + return seriesNoLabeled; + } + + public ExpressionResult newSeriesLabeledResult() { + ExpressionResult seriesLabeled = new ExpressionResult(); + seriesLabeled.setLabeledResult(true); + seriesLabeled.setType(ExpressionResultType.TIME_SERIES_VALUES); + MQEValues mqeValues1 = new MQEValues(); + mqeValues1.setMetric(newMetadata("label", "1")); + mqeValues1.getValues().add(newMQEValue("100", 100)); + mqeValues1.getValues().add(newMQEValue("300", 300)); + MQEValues mqeValues2 = new MQEValues(); + mqeValues2.setMetric(newMetadata("label", "2")); + mqeValues2.getValues().add(newMQEValue("100", 101)); + mqeValues2.getValues().add(newMQEValue("300", 301)); + seriesLabeled.getResults().add(mqeValues1); + seriesLabeled.getResults().add(mqeValues2); + return seriesLabeled; + } + + public ExpressionResult newSeriesLabeledResult(double id1001, double id3001, double id1002, double id3002) { + ExpressionResult seriesLabeled = new ExpressionResult(); + seriesLabeled.setLabeledResult(true); + seriesLabeled.setType(ExpressionResultType.TIME_SERIES_VALUES); + MQEValues mqeValues1 = new MQEValues(); + mqeValues1.setMetric(newMetadata("label", "1")); + mqeValues1.getValues().add(newMQEValue("100", id1001)); + mqeValues1.getValues().add(newMQEValue("300", id3001)); + MQEValues mqeValues2 = new MQEValues(); + mqeValues2.setMetric(newMetadata("label", "2")); + mqeValues2.getValues().add(newMQEValue("100", id1002)); + mqeValues2.getValues().add(newMQEValue("300", id3002)); + seriesLabeled.getResults().add(mqeValues1); + seriesLabeled.getResults().add(mqeValues2); + return seriesLabeled; + } + + public ExpressionResult newListResult() { + ExpressionResult listResult = new ExpressionResult(); + listResult.setType(ExpressionResultType.SORTED_LIST); + MQEValues mqeValues = new MQEValues(); + mqeValues.getValues().add(newMQEValue("service_A", 100)); + mqeValues.getValues().add(newMQEValue("service_B", 300)); + listResult.getResults().add(mqeValues); + return listResult; + } + + public ExpressionResult newListResult(double serviceA, double serviceB) { + ExpressionResult listResult = new ExpressionResult(); + listResult.setType(ExpressionResultType.SORTED_LIST); + MQEValues mqeValues = new MQEValues(); + mqeValues.getValues().add(newMQEValue("service_A", serviceA)); + mqeValues.getValues().add(newMQEValue("service_B", serviceB)); + listResult.getResults().add(mqeValues); + return listResult; + } + + public ExpressionResult newSingleResult() { + ExpressionResult listResult = new ExpressionResult(); + listResult.setType(ExpressionResultType.SINGLE_VALUE); + MQEValues mqeValues = new MQEValues(); + mqeValues.getValues().add(newMQEValue(null, 1000)); + listResult.getResults().add(mqeValues); + return listResult; + } + + public MQEValue newMQEValue(String id, double value) { + MQEValue mqeValue = new MQEValue(); + mqeValue.setId(id); + mqeValue.setDoubleValue(value); + return mqeValue; + } + + public Metadata newMetadata(String key, String value) { + Metadata metadata = new Metadata(); + metadata.getLabels().add(new KeyValue(key, value)); + return metadata; + } +} diff --git a/oap-server/server-starter/src/main/resources/ui-initialized-templates/general/general-instance.json b/oap-server/server-starter/src/main/resources/ui-initialized-templates/general/general-instance.json index 2194d85ac7..2a371d7ded 100644 --- a/oap-server/server-starter/src/main/resources/ui-initialized-templates/general/general-instance.json +++ b/oap-server/server-starter/src/main/resources/ui-initialized-templates/general/general-instance.json @@ -724,12 +724,6 @@ "h": 12, "i": "0", "type": "Widget", - "metricTypes": [ - "readMetricsValues" - ], - "metrics": [ - "meter_http_server_requests_count" - ], "graph": { "type": "Line", "step": false, @@ -740,7 +734,19 @@ }, "widget": { "title": "HTTP Request (Count)" - } + }, + "metricMode": "Expression", + "metricConfig": [ + { + "label": "count" + } + ], + "expressions": [ + "meter_http_server_requests_count" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES" + ] }, { "x": 6, @@ -749,12 +755,6 @@ "h": 12, "i": "1", "type": "Widget", - "metricTypes": [ - "readMetricsValues" - ], - "metrics": [ - "meter_http_server_requests_duration" - ], "graph": { "type": "Line", "step": false, @@ -766,7 +766,19 @@ "widget": { "title": "HTTP Request Duration (ms)" }, - "associate": [] + "associate": [], + "metricMode": "Expression", + "metricConfig": [ + { + "label": "duration" + } + ], + "expressions": [ + "meter_http_server_requests_duration" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES" + ] }, { "x": 6, @@ -800,12 +812,6 @@ "h": 12, "i": "3", "type": "Widget", - "metricTypes": [ - "readMetricsValues" - ], - "metrics": [ - "meter_system_cpu_usage" - ], "graph": { "type": "Line", "step": false, @@ -816,7 +822,19 @@ }, "widget": { "title": "OS CPU Usage (%)" - } + }, + "metricMode": "Expression", + "metricConfig": [ + { + "label": "usage" + } + ], + "expressions": [ + "meter_system_cpu_usage" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES" + ] }, { "x": 12, @@ -825,16 +843,6 @@ "h": 12, "i": "4", "type": "Widget", - "metricTypes": [ - "readMetricsValues", - "readMetricsValues", - "readMetricsValues" - ], - "metrics": [ - "meter_jdbc_connections_max", - "meter_jdbc_connections_active", - "meter_jdbc_connections_idle" - ], "metricConfig": [ { "label": "max" @@ -856,7 +864,18 @@ }, "widget": { "title": "JDBC Connections (Count)" - } + }, + "metricMode": "Expression", + "expressions": [ + "meter_jdbc_connections_max", + "meter_jdbc_connections_active", + "meter_jdbc_connections_idle" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" + ] }, { "x": 18, @@ -865,17 +884,6 @@ "h": 12, "i": "5", "type": "Widget", - "metricTypes": [ - "readMetricsValues", - "readMetricsValues", - "readMetricsValues", - "readMetricsValues" - ], - "metrics": [ - "meter_tomcat_sessions_active_max", - "meter_tomcat_sessions_active_current", - "meter_tomcat_sessions_rejected" - ], "metricConfig": [ { "label": "active_max" @@ -897,7 +905,18 @@ }, "widget": { "title": "Tomcat Session (Count)" - } + }, + "metricMode": "Expression", + "expressions": [ + "meter_tomcat_sessions_active_max", + "meter_tomcat_sessions_active_current", + "meter_tomcat_sessions_rejected" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" + ] }, { "x": 12, @@ -906,12 +925,6 @@ "h": 12, "i": "6", "type": "Widget", - "metricTypes": [ - "readMetricsValues" - ], - "metrics": [ - "meter_system_load_average_1m" - ], "graph": { "type": "Line", "step": false, @@ -923,7 +936,19 @@ "widget": { "title": "OS System Load" }, - "associate": [] + "associate": [], + "metricConfig": [ + { + "label": "load" + } + ], + "metricMode": "Expression", + "expressions": [ + "meter_system_load_average_1m" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES" + ] }, { "x": 18, @@ -932,14 +957,6 @@ "h": 12, "i": "7", "type": "Widget", - "metricTypes": [ - "readMetricsValues", - "readMetricsValues" - ], - "metrics": [ - "meter_process_files_max", - "meter_process_files_open" - ], "metricConfig": [ { "label": "max" @@ -959,7 +976,16 @@ "widget": { "title": "OS Process File (Count)" }, - "associate": [] + "associate": [], + "metricMode": "Expression", + "expressions": [ + "meter_process_files_max", + "meter_process_files_open" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" + ] }, { "x": 0, @@ -968,12 +994,6 @@ "h": 12, "i": "8", "type": "Widget", - "metricTypes": [ - "readMetricsValues" - ], - "metrics": [ - "meter_jvm_gc_pause_duration" - ], "graph": { "type": "Line", "step": false, @@ -984,7 +1004,19 @@ }, "widget": { "title": "JVM GC Pause Duration (ms)" - } + }, + "metricMode": "Expression", + "metricConfig": [ + { + "label": "duration" + } + ], + "expressions": [ + "meter_jvm_gc_pause_duration" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES" + ] }, { "x": 6, @@ -993,16 +1025,6 @@ "h": 12, "i": "9", "type": "Widget", - "metricTypes": [ - "readMetricsValues", - "readMetricsValues", - "readMetricsValues" - ], - "metrics": [ - "meter_jvm_memory_max", - "meter_jvm_memory_used", - "meter_jvm_memory_committed" - ], "graph": { "type": "Line", "step": false, @@ -1014,24 +1036,21 @@ "associate": [], "metricConfig": [ { - "calculation": "byteToMB", - "label": "max", - "unit": "MB" - }, - { - "calculation": "byteToMB", - "label": "used", - "unit": "MB" - }, - { - "calculation": "byteToMB", - "label": "committed", - "unit": "MB" + "label": "max" } ], "widget": { "title": "JVM Memory (MB)" - } + }, + "metricMode": "Expression", + "expressions": [ + "meter_jvm_memory_max/1048576", + "meter_jvm_memory_used/1048576" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" + ] }, { "x": 12, @@ -1040,16 +1059,6 @@ "h": 12, "i": "10", "type": "Widget", - "metricTypes": [ - "readMetricsValues", - "readMetricsValues", - "readMetricsValues" - ], - "metrics": [ - "meter_jvm_threads_peak", - "meter_jvm_threads_live", - "meter_jvm_threads_daemon" - ], "metricConfig": [ { "label": "peak" @@ -1071,7 +1080,18 @@ }, "widget": { "title": "JVM Thread (Count)" - } + }, + "metricMode": "Expression", + "expressions": [ + "meter_jvm_threads_peak", + "meter_jvm_threads_live", + "meter_jvm_threads_daemon" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" + ] }, { "x": 18, @@ -1080,14 +1100,6 @@ "h": 12, "i": "11", "type": "Widget", - "metricTypes": [ - "readMetricsValues", - "readMetricsValues" - ], - "metrics": [ - "meter_jvm_classes_loaded", - "meter_jvm_classes_unloaded" - ], "metricConfig": [ { "label": "loaded" @@ -1106,7 +1118,16 @@ }, "widget": { "title": "JVM classes (Count)" - } + }, + "metricMode": "Expression", + "expressions": [ + "meter_jvm_classes_loaded", + "meter_jvm_classes_unloaded" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" + ] } ] }, @@ -1131,16 +1152,12 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ - "meter_instance_golang_heap_alloc" + "metricMode": "Expression", + "expressions": [ + "meter_instance_golang_heap_alloc/1048576" ], - "metricTypes": [ - "readMetricsValues" - ], - "metricConfig": [ - { - "calculation": "byteToMB" - } + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] }, { @@ -1161,16 +1178,12 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ - "meter_instance_golang_stack_used" + "metricMode": "Expression", + "expressions": [ + "meter_instance_golang_stack_used/1048576" ], - "metricTypes": [ - "readMetricsValues" - ], - "metricConfig": [ - { - "calculation": "byteToMB" - } + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] }, { @@ -1187,16 +1200,17 @@ "type": "Bar", "showBackground": true }, - "metrics": [ - "meter_instance_golang_gc_pause_time" - ], - "metricTypes": [ - "readMetricsValues" - ], "metricConfig": [ { - "calculation": "nanosecondToMillisecond" + "label": "pause_time" } + ], + "metricMode": "Expression", + "expressions": [ + "meter_instance_golang_gc_pause_time" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] }, { @@ -1238,11 +1252,17 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ + "metricMode": "Expression", + "metricConfig": [ + { + "label": "live_goroutines_num" + } + ], + "expressions": [ "meter_instance_golang_live_goroutines_num" ], - "metricTypes": [ - "readMetricsValues" + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] }, { @@ -1263,11 +1283,17 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ + "metricMode": "Expression", + "metricConfig": [ + { + "label": "os_threads_num" + } + ], + "expressions": [ "meter_instance_golang_os_threads_num" ], - "metricTypes": [ - "readMetricsValues" + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] }, { @@ -1288,11 +1314,17 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ + "metricMode": "Expression", + "metricConfig": [ + { + "label": "host_cpu_used_rate" + } + ], + "expressions": [ "meter_instance_host_cpu_used_rate" ], - "metricTypes": [ - "readMetricsValues" + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] }, { @@ -1313,11 +1345,17 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ + "metricMode": "Expression", + "metricConfig": [ + { + "label": "host_mem_used_rate" + } + ], + "expressions": [ "meter_instance_host_mem_used_rate" ], - "metricTypes": [ - "readMetricsValues" + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] } ] @@ -1341,14 +1379,6 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ - "meter_instance_pvm_total_cpu_utilization", - "meter_instance_pvm_process_cpu_utilization" - ], - "metricTypes": [ - "readMetricsValues", - "readMetricsValues" - ], "metricConfig": [ { "label": "total_cpu_utilization" @@ -1356,6 +1386,15 @@ { "label": "process_cpu_utilization" } + ], + "metricMode": "Expression", + "expressions": [ + "meter_instance_pvm_total_cpu_utilization", + "meter_instance_pvm_process_cpu_utilization" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" ] }, { @@ -1376,11 +1415,17 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ + "metricMode": "Expression", + "metricConfig": [ + { + "label": "thread_active_count" + } + ], + "expressions": [ "meter_instance_pvm_thread_active_count" ], - "metricTypes": [ - "readMetricsValues" + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] }, { @@ -1397,26 +1442,27 @@ "type": "Bar", "showBackground": true }, - "metrics": [ + "metricConfig": [ + { + "label": "g0" + }, + { + "label": "g1" + }, + { + "label": "g2" + } + ], + "metricMode": "Expression", + "expressions": [ "meter_instance_pvm_gc_g0", "meter_instance_pvm_gc_g1", "meter_instance_pvm_gc_g2" ], - "metricTypes": [ - "readMetricsValues", - "readMetricsValues", - "readMetricsValues" - ], - "metricConfig": [ - { - "label": "gc_g0" - }, - { - "label": "gc_g1" - }, - { - "label": "gc_g2" - } + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" ] }, { @@ -1435,14 +1481,6 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ - "meter_instance_pvm_total_mem_utilization", - "meter_instance_pvm_process_mem_utilization" - ], - "metricTypes": [ - "readMetricsValues", - "readMetricsValues" - ], "metricConfig": [ { "label": "total_mem_utilization" @@ -1450,6 +1488,15 @@ { "label": "process_mem_utilization" } + ], + "metricMode": "Expression", + "expressions": [ + "meter_instance_pvm_total_mem_utilization", + "meter_instance_pvm_process_mem_utilization" + ], + "typesOfMQE": [ + "TIME_SERIES_VALUES", + "TIME_SERIES_VALUES" ] }, { @@ -1470,11 +1517,12 @@ "showXAxis": true, "showYAxis": true }, - "metrics": [ + "metricMode": "Expression", + "expressions": [ "meter_instance_pvm_gc_time" ], - "metricTypes": [ - "readMetricsValues" + "typesOfMQE": [ + "TIME_SERIES_VALUES" ] } ] diff --git a/test/e2e-v2/cases/mqe/docker-compose.yml b/test/e2e-v2/cases/mqe/docker-compose.yml new file mode 100644 index 0000000000..be02077e5e --- /dev/null +++ b/test/e2e-v2/cases/mqe/docker-compose.yml @@ -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. + +version: '2.1' + +services: + oap: + extends: + file: ../../script/docker-compose/base-compose.yml + service: oap + ports: + - 12800 + networks: + - e2e + + provider: + extends: + file: ../../script/docker-compose/base-compose.yml + service: provider + ports: + - 9090 + depends_on: + oap: + condition: service_healthy + + consumer: + extends: + file: ../../script/docker-compose/base-compose.yml + service: consumer + ports: + - 9092 + depends_on: + provider: + condition: service_healthy + +networks: + e2e: diff --git a/test/e2e-v2/cases/mqe/e2e.yaml b/test/e2e-v2/cases/mqe/e2e.yaml new file mode 100644 index 0000000000..d836735694 --- /dev/null +++ b/test/e2e-v2/cases/mqe/e2e.yaml @@ -0,0 +1,47 @@ +# 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. + +# This file is used to show how to write configuration files and can be used to test. + +setup: + env: compose + file: docker-compose.yml + timeout: 20m + init-system-environment: ../../script/env + steps: + - name: set PATH + command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH + - name: install yq + command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq + - name: install swctl + command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl + +trigger: + action: http + interval: 3s + times: 10 + url: http://${consumer_host}:${consumer_9092}/users + method: POST + body: '{"id":"123","name":"skywalking"}' + headers: + "Content-Type": "application/json" + +verify: + retry: + count: 20 + interval: 3s + cases: + - includes: + - ./mqe-cases.yaml diff --git a/test/e2e-v2/cases/mqe/expected/aggregation-OP.yml b/test/e2e-v2/cases/mqe/expected/aggregation-OP.yml new file mode 100644 index 0000000000..a9524ad4ad --- /dev/null +++ b/test/e2e-v2/cases/mqe/expected/aggregation-OP.yml @@ -0,0 +1,24 @@ +# 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: SINGLE_VALUE +results: + - metric: + labels: [] + values: + - id: null + value: "100" + traceid: null +error: null diff --git a/test/e2e-v2/cases/mqe/expected/binary-OP.yml b/test/e2e-v2/cases/mqe/expected/binary-OP.yml new file mode 100644 index 0000000000..0dbec566ab --- /dev/null +++ b/test/e2e-v2/cases/mqe/expected/binary-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: "650" + traceid: null + - id: {{ notEmpty .id }} + value: null + traceid: null + {{- end}} +{{- end}} +error: null diff --git a/test/e2e-v2/cases/mqe/expected/func-OP.yml b/test/e2e-v2/cases/mqe/expected/func-OP.yml new file mode 100644 index 0000000000..2215b68d54 --- /dev/null +++ b/test/e2e-v2/cases/mqe/expected/func-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: "300" + traceid: null + - id: {{ notEmpty .id }} + value: null + traceid: null + {{- end}} +{{- end}} +error: null diff --git a/test/e2e-v2/cases/mqe/expected/no-OP.yml b/test/e2e-v2/cases/mqe/expected/no-OP.yml new file mode 100644 index 0000000000..a4474f13e8 --- /dev/null +++ b/test/e2e-v2/cases/mqe/expected/no-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/expected/relabels-OP.yml b/test/e2e-v2/cases/mqe/expected/relabels-OP.yml new file mode 100644 index 0000000000..519c212556 --- /dev/null +++ b/test/e2e-v2/cases/mqe/expected/relabels-OP.yml @@ -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. + +type: TIME_SERIES_VALUES +results: +{{- contains .results }} + - metric: + labels: + - key: label + value: "P50" + values: + {{- contains .values }} + - id: {{ notEmpty .id }} + value: {{ .value }} + traceid: null + - id: {{ notEmpty .id }} + value: null + traceid: null + {{- end}} + - metric: + labels: + - key: label + value: "P75" + values: + {{- contains .values }} + - id: {{ notEmpty .id }} + value: {{ .value }} + traceid: null + - id: {{ notEmpty .id }} + value: null + traceid: null + {{- end}} + - metric: + labels: + - key: label + value: "P90" + 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/expected/relabels-binary-OP.yml b/test/e2e-v2/cases/mqe/expected/relabels-binary-OP.yml new file mode 100644 index 0000000000..f06594984a --- /dev/null +++ b/test/e2e-v2/cases/mqe/expected/relabels-binary-OP.yml @@ -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. + +type: TIME_SERIES_VALUES +results: +{{- contains .results }} + - metric: + labels: + - key: label + value: "P50" + values: + {{- contains .values }} + - id: {{ notEmpty .id }} + value: "1" + traceid: null + - id: {{ notEmpty .id }} + value: null + traceid: null + {{- end}} + - metric: + labels: + - key: label + value: "P75" + values: + {{- contains .values }} + - id: {{ notEmpty .id }} + value: "1" + traceid: null + - id: {{ notEmpty .id }} + value: null + traceid: null + {{- end}} + - metric: + labels: + - key: label + value: "P90" + values: + {{- contains .values }} + - id: {{ notEmpty .id }} + value: "1" + traceid: null + - id: {{ notEmpty .id }} + value: null + traceid: null + {{- end}} +{{- end}} +error: null diff --git a/test/e2e-v2/cases/mqe/expected/topN-OP-instance.yml b/test/e2e-v2/cases/mqe/expected/topN-OP-instance.yml new file mode 100644 index 0000000000..18d0a1a901 --- /dev/null +++ b/test/e2e-v2/cases/mqe/expected/topN-OP-instance.yml @@ -0,0 +1,24 @@ +# 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: SORTED_LIST +results: + - metric: + labels: [] + values: + - id: provider1 + value: "100" + traceid: null +error: null diff --git a/test/e2e-v2/cases/mqe/expected/topN-OP-service.yml b/test/e2e-v2/cases/mqe/expected/topN-OP-service.yml new file mode 100644 index 0000000000..4ac5c7cbe5 --- /dev/null +++ b/test/e2e-v2/cases/mqe/expected/topN-OP-service.yml @@ -0,0 +1,27 @@ +# 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: SORTED_LIST +results: + - metric: + labels: [] + values: + - id: e2e-service-consumer + value: "100" + traceid: null + - id: e2e-service-provider + value: "100" + traceid: null +error: null diff --git a/test/e2e-v2/cases/mqe/mqe-cases.yaml b/test/e2e-v2/cases/mqe/mqe-cases.yaml new file mode 100644 index 0000000000..fcaf79e36f --- /dev/null +++ b/test/e2e-v2/cases/mqe/mqe-cases.yaml @@ -0,0 +1,51 @@ +# 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. + +# E2E is mainly used to test expressions and query, specific calculations tests please refer to the +# oap-server/server-query-plugin/query-graphql-plugin/src/test/java/org/apache/skywalking/oap/query/graphql/mqe +cases: + # service metrics + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression=service_sla --service-name=e2e-service-provider + expected: expected/no-OP.yml + + # binary-OP + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="service_sla * 2 /100 + 500 - 50" --service-name=e2e-service-provider + expected: expected/binary-OP.yml + + # aggregation-OP + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="avg(service_sla/100)" --service-name=e2e-service-provider + expected: expected/aggregation-OP.yml + + # func-OP + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="abs(service_sla-10300)" --service-name=e2e-service-provider + expected: expected/func-OP.yml + + # topN-OP-service + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="top_n(service_sla,3,des)/100" + expected: expected/topN-OP-service.yml + + # topN-OP-service + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="top_n(service_instance_sla,3,des)/100" --service-name=e2e-service-provider + expected: expected/topN-OP-instance.yml + + # select labels and relabels + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="relabels(service_percentile{label='0,1,2'},label='P50,P75,P90')" --service-name=e2e-service-provider + expected: expected/relabels-OP.yml + + # relabels and calculate + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="relabels(service_percentile{label='0,1,2'},label='P50,P75,P90')/relabels(service_percentile{label='0,1,2'},label='P50,P75,P90')" --service-name=e2e-service-provider + 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