This is an automated email from the ASF dual-hosted git repository. wankai 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 61b4674c16 Support aggregation operators in PromQL query. (#12431) 61b4674c16 is described below commit 61b4674c16f392e1e8ee01101d4e68278fb6b0af Author: weixiang1862 <652048...@qq.com> AuthorDate: Fri Jul 12 16:29:03 2024 +0800 Support aggregation operators in PromQL query. (#12431) --- docs/en/api/promql-service.md | 27 ++++ docs/en/changes/changes.md | 1 + .../skywalking/promql/rt/grammar/PromQLLexer.g4 | 9 ++ .../skywalking/promql/rt/grammar/PromQLParser.g4 | 9 ++ .../oap/query/promql/entity/TimeValuePair.java | 4 +- .../oap/query/promql/rt/PromOpUtils.java | 78 ++++++++++ .../query/promql/rt/PromQLExprQueryVisitor.java | 48 +++++++ .../rt/parser/PromQLExprQueryVisitorTest.java | 159 +++++++++++++++++++++ ...ervice-metric-labeled-matrix-aggregate-by-p.yml | 46 ++++++ ...e-metric-labeled-matrix-aggregate-without-p.yml | 32 +++++ test/e2e-v2/cases/promql/promql-cases.yaml | 4 + 11 files changed, 415 insertions(+), 2 deletions(-) diff --git a/docs/en/api/promql-service.md b/docs/en/api/promql-service.md index 8efb66e82f..88861ae03e 100644 --- a/docs/en/api/promql-service.md +++ b/docs/en/api/promql-service.md @@ -106,6 +106,33 @@ For example: service_cpm{service='service_A', layer='$layer'} > service_cpm{service='service_B', layer='$layer'} ``` +### Aggregation operators +[Prometheus Docs Reference](https://prometheus.io/docs/prometheus/latest/querying/operators/#aggregation-operators) + +| Operator | Definition | Support | +|----------|---------------------------------------|---------| +| sum | calculate sum over dimensions | yes | +| min | select minimum over dimensions | yes | +| max | select maximum over dimensions | yes | +| avg | calculate the average over dimensions | yes | + +For example: + +If the metric `http_requests_total` had time series that fan out by `service`, `service_instance_id`, and `group` labels, +we could calculate the total number of seen HTTP requests per service and group over all service instances via: + +``` +sum by (service, group) (http_requests_total{service='$service', layer='$layer'}) +``` +Which is equivalent to: +``` +sum without (service_instance_id) (http_requests_total{service='$service', layer='$layer'}) +``` +If we are just interested in the total of HTTP requests we have seen in all services, we could simply write: +``` +sum(http_requests_total{service='$service', layer='$layer'}) +``` + ### HTTP API #### Expression queries diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md index f41d34f202..d0b0736441 100644 --- a/docs/en/changes/changes.md +++ b/docs/en/changes/changes.md @@ -31,6 +31,7 @@ * Fix expression of graph `Current QPS` in MySQL dashboard. * Support tracing logs query for debugging. * BanyanDB: fix Tag autocomplete data storage and query. +* Support aggregation operators in PromQL query. #### UI * Highlight search log keywords. diff --git a/oap-server/server-query-plugin/promql-plugin/src/main/antlr4/org/apache/skywalking/promql/rt/grammar/PromQLLexer.g4 b/oap-server/server-query-plugin/promql-plugin/src/main/antlr4/org/apache/skywalking/promql/rt/grammar/PromQLLexer.g4 index c82dd1a0c8..5fc2b7c5da 100644 --- a/oap-server/server-query-plugin/promql-plugin/src/main/antlr4/org/apache/skywalking/promql/rt/grammar/PromQLLexer.g4 +++ b/oap-server/server-query-plugin/promql-plugin/src/main/antlr4/org/apache/skywalking/promql/rt/grammar/PromQLLexer.g4 @@ -45,6 +45,15 @@ LT: '<'; GTE: '>='; GT: '>'; +// Aggregation operators +AVG: 'avg'; +MAX: 'max'; +MIN: 'min'; +SUM: 'sum'; + +BY: 'by'; +WITHOUT: 'without'; + // Literals NUMBER: Digit+ (DOT Digit+)?; DURATION: Digit+ ('ms' | 's' | 'm' | 'h' | 'd' | 'w'); diff --git a/oap-server/server-query-plugin/promql-plugin/src/main/antlr4/org/apache/skywalking/promql/rt/grammar/PromQLParser.g4 b/oap-server/server-query-plugin/promql-plugin/src/main/antlr4/org/apache/skywalking/promql/rt/grammar/PromQLParser.g4 index 847e23aabd..57b2681caa 100644 --- a/oap-server/server-query-plugin/promql-plugin/src/main/antlr4/org/apache/skywalking/promql/rt/grammar/PromQLParser.g4 +++ b/oap-server/server-query-plugin/promql-plugin/src/main/antlr4/org/apache/skywalking/promql/rt/grammar/PromQLParser.g4 @@ -27,6 +27,8 @@ expression | expression mulDivMod expression # mulDivModOp | expression addSub expression # addSubOp | expression compare expression # compareOp + | aggregationFunc (aggregationClause)? L_PAREN expression R_PAREN # aggregationOp + | aggregationFunc L_PAREN expression R_PAREN (aggregationClause)? # aggregationOp ; expressionNode: metricInstant| metricRange| numberLiteral| badRange; @@ -35,6 +37,12 @@ addSub: ADD | SUB ; mulDivMod: MUL | DIV | MOD; compare: (DEQ | NEQ | LTE | LT | GTE | GT) BOOL?; +aggregationFunc: + AVG | SUM | MAX | MIN; + +aggregationClause: + (BY | WITHOUT) L_PAREN labelNameList R_PAREN; + metricName: NAME_STRING; metricInstant: metricName | metricName L_BRACE labelList? R_BRACE; metricRange: metricInstant L_BRACKET DURATION R_BRACKET; @@ -43,6 +51,7 @@ labelName: NAME_STRING; labelValue: VALUE_STRING; label: labelName EQ labelValue; labelList: label (COMMA label)*; +labelNameList: labelName (COMMA labelName)*; numberLiteral: NUMBER; diff --git a/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/entity/TimeValuePair.java b/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/entity/TimeValuePair.java index 68e32065c2..3d29522807 100644 --- a/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/entity/TimeValuePair.java +++ b/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/entity/TimeValuePair.java @@ -25,8 +25,8 @@ import org.apache.skywalking.oap.query.promql.entity.codec.TimeValuePairSerializ @Data @JsonSerialize(using = TimeValuePairSerializer.class) public class TimeValuePair { - private final long time; - private final String value; + private long time; + private String value; public TimeValuePair(final long time, String value) { this.time = time; diff --git a/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/rt/PromOpUtils.java b/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/rt/PromOpUtils.java index d439433ace..c29ba62e08 100644 --- a/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/rt/PromOpUtils.java +++ b/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/rt/PromOpUtils.java @@ -20,8 +20,18 @@ package org.apache.skywalking.oap.query.promql.rt; import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; +import org.apache.skywalking.mqe.rt.operation.aggregatelabels.AggregateLabelsFunc; +import org.apache.skywalking.mqe.rt.operation.aggregatelabels.AggregateLabelsFuncFactory; +import org.apache.skywalking.mqe.rt.operation.aggregatelabels.AvgAggregateLabelsFunc; +import org.apache.skywalking.mqe.rt.operation.aggregatelabels.MaxAggregateLabelsFunc; +import org.apache.skywalking.mqe.rt.operation.aggregatelabels.MinAggregateLabelsFunc; +import org.apache.skywalking.mqe.rt.operation.aggregatelabels.SumAggregateLabelsFunc; +import org.apache.skywalking.oap.query.promql.entity.LabelValuePair; +import org.apache.skywalking.oap.query.promql.entity.MetricInfo; import org.apache.skywalking.oap.query.promql.entity.MetricRangeData; import org.apache.skywalking.oap.query.promql.entity.TimeValuePair; import org.apache.skywalking.oap.query.promql.rt.exception.IllegalExpressionException; @@ -33,10 +43,14 @@ import org.apache.skywalking.oap.server.core.query.PointOfTime; import org.apache.skywalking.oap.server.core.query.input.Duration; import org.apache.skywalking.oap.server.core.query.type.KVInt; import org.apache.skywalking.oap.server.core.query.type.MetricsValues; +import org.apache.skywalking.oap.server.library.util.StringUtil; import org.apache.skywalking.promql.rt.grammar.PromQLParser; import org.joda.time.format.PeriodFormatter; import org.joda.time.format.PeriodFormatterBuilder; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toList; + public class PromOpUtils { static MetricsRangeResult matrixScalarBinaryOp(MetricsRangeResult matrix, ScalarResult scalar, int opType) { @@ -92,6 +106,70 @@ public class PromOpUtils { return result; } + static MetricsRangeResult matrixAggregateOp(MetricsRangeResult result, int funcType, List<String> groupingBy) { + List<MetricRangeData> metricDataList = result.getMetricDataList(); + Map<List<LabelValuePair>, List<MetricRangeData>> groupedResult = metricDataList + .stream().collect(groupingBy(rangeData -> getLabels(groupingBy, rangeData), LinkedHashMap::new, toList())); + + MetricsRangeResult rangeResult = new MetricsRangeResult(); + rangeResult.setResultType(ParseResultType.METRICS_RANGE); + AggregateLabelsFuncFactory factory = getAggregateFuncFactory(funcType); + groupedResult.forEach((labels, dataList) -> { + if (dataList.isEmpty()) { + return; + } + List<TimeValuePair> combineTo = dataList.get(0).getValues(); + for (int i = 0; i < combineTo.size(); i++) { + AggregateLabelsFunc aggregateLabelsFunc = factory.getAggregateLabelsFunc(); + for (MetricRangeData rangeData : dataList) { + TimeValuePair toCombine = rangeData.getValues().get(i); + if (StringUtil.isNotBlank(toCombine.getValue())) { + aggregateLabelsFunc.combine(Double.parseDouble(toCombine.getValue())); + } + } + + TimeValuePair timeValuePair = combineTo.get(i); + Double aggResult = aggregateLabelsFunc.getResult(); + if (aggResult != null) { + timeValuePair.setValue(aggResult.toString()); + } + } + MetricRangeData rangeData = new MetricRangeData(); + rangeData.setMetric(new MetricInfo(null)); + rangeData.getMetric().setLabels(labels); + rangeData.setValues(combineTo); + rangeResult.getMetricDataList().add(rangeData); + }); + + return rangeResult; + } + + private static AggregateLabelsFuncFactory getAggregateFuncFactory(int funcType) { + switch (funcType) { + case PromQLParser.AVG: + return AvgAggregateLabelsFunc::new; + case PromQLParser.SUM: + return SumAggregateLabelsFunc::new; + case PromQLParser.MAX: + return MaxAggregateLabelsFunc::new; + case PromQLParser.MIN: + return MinAggregateLabelsFunc::new; + default: + throw new IllegalArgumentException("Unsupported aggregate function type: " + funcType); + } + } + + private static List<LabelValuePair> getLabels(List<String> groupingBy, MetricRangeData data) { + return groupingBy.stream() + .map( + labelName -> + data.getMetric().getLabels() + .stream().filter(label -> labelName.equals(label.getLabelName())) + .findAny().orElseGet(() -> new LabelValuePair(labelName, "")) + ) + .collect(toList()); + } + static double scalarBinaryOp(double leftValue, double rightValue, int opType) { double calculatedResult = 0; switch (opType) { diff --git a/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/rt/PromQLExprQueryVisitor.java b/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/rt/PromQLExprQueryVisitor.java index e9570a590f..f46bf2ddd0 100644 --- a/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/rt/PromQLExprQueryVisitor.java +++ b/oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/rt/PromQLExprQueryVisitor.java @@ -26,7 +26,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; +import org.antlr.v4.runtime.RuleContext; import org.apache.skywalking.oap.query.promql.entity.ErrorType; import org.apache.skywalking.oap.query.promql.entity.LabelName; import org.apache.skywalking.oap.query.promql.entity.LabelValuePair; @@ -58,6 +60,7 @@ import org.apache.skywalking.oap.server.core.query.type.Record; import org.apache.skywalking.oap.server.core.query.type.SelectedRecord; import org.apache.skywalking.oap.server.core.storage.annotation.Column; import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata; +import org.apache.skywalking.oap.server.library.util.CollectionUtils; import org.apache.skywalking.oap.server.library.util.StringUtil; import org.apache.skywalking.promql.rt.grammar.PromQLParser; import org.apache.skywalking.promql.rt.grammar.PromQLParserBaseVisitor; @@ -135,6 +138,51 @@ public class PromQLExprQueryVisitor extends PromQLParserBaseVisitor<ParseResult> return compareOp(left, right, opType, boolModifier); } + @Override + public ParseResult visitAggregationOp(final PromQLParser.AggregationOpContext ctx) { + ParseResult parseResult = visit(ctx.expression()); + if (StringUtil.isNotBlank(parseResult.getErrorInfo())) { + return parseResult; + } + + if (!parseResult.getResultType().equals(ParseResultType.METRICS_RANGE)) { + ParseResult result = new ParseResult(); + result.setErrorType(ErrorType.BAD_DATA); + result.setErrorInfo("Expected type instant vector in aggregation expression."); + return result; + } + + MetricsRangeResult metricsRangeResult = (MetricsRangeResult) parseResult; + if (CollectionUtils.isEmpty(metricsRangeResult.getMetricDataList())) { + return metricsRangeResult; + } + + List<String> resultLabelNames = metricsRangeResult.getMetricDataList() + .get(0).getMetric().getLabels() + .stream().map(LabelValuePair::getLabelName) + .collect(Collectors.toList()); + + List<String> groupingBy = new ArrayList<>(); + PromQLParser.AggregationClauseContext clauseContext = ctx.aggregationClause(); + if (clauseContext != null) { + List<String> clauseGroupingBy = clauseContext.labelNameList().labelName().stream() + .map(RuleContext::getText) + .filter(resultLabelNames::contains) + .collect(Collectors.toList()); + if (clauseContext.getStart().getType() == PromQLParser.WITHOUT) { + groupingBy = resultLabelNames.stream() + .filter(labelName -> !clauseGroupingBy.contains(labelName)) + .collect(Collectors.toList()); + } else { + groupingBy = clauseGroupingBy; + } + } + + return PromOpUtils.matrixAggregateOp( + (MetricsRangeResult) parseResult, ctx.aggregationFunc().getStart().getType(), groupingBy + ); + } + private ParseResult compareOp(ParseResult left, ParseResult right, int opType, boolean boolModifier) { try { if (left.getResultType() == ParseResultType.SCALAR && right.getResultType() == ParseResultType.SCALAR) { diff --git a/oap-server/server-query-plugin/promql-plugin/src/test/java/org/apache/skywalking/promql/rt/parser/PromQLExprQueryVisitorTest.java b/oap-server/server-query-plugin/promql-plugin/src/test/java/org/apache/skywalking/promql/rt/parser/PromQLExprQueryVisitorTest.java index 60109c8a64..e9876a180e 100644 --- a/oap-server/server-query-plugin/promql-plugin/src/test/java/org/apache/skywalking/promql/rt/parser/PromQLExprQueryVisitorTest.java +++ b/oap-server/server-query-plugin/promql-plugin/src/test/java/org/apache/skywalking/promql/rt/parser/PromQLExprQueryVisitorTest.java @@ -25,6 +25,7 @@ import lombok.SneakyThrows; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree; +import org.apache.skywalking.oap.query.promql.entity.LabelValuePair; import org.apache.skywalking.oap.query.promql.entity.TimeValuePair; import org.apache.skywalking.oap.query.promql.handler.PromQLApiHandler; import org.apache.skywalking.oap.query.promql.rt.result.ParseResultType; @@ -121,6 +122,108 @@ public class PromQLExprQueryVisitorTest { }); } + public static Collection<Object[]> aggregateData() { + // {service_instance_id=a,group=g} 0, 1, 2 + // {service_instance_id=b,group=g} 2, 3, 4 + return Arrays.asList(new Object[][] { + { + "MetricsAggregationOpSum", + PromQLApiHandler.QueryType.RANGE, + "sum by(group) (http_requests_total{service='serviceA', layer='GENERAL'})", + List.of( + List.of( + new TimeValuePair(TIME_2023022010, "2.0"), + new TimeValuePair(TIME_2023022011, "4.0"), + new TimeValuePair(TIME_2023022012, "6.0") + ) + ), + List.of( + List.of( + new LabelValuePair("group", "g") + ) + ) + }, + { + "MetricsAggregationOpAvg", + PromQLApiHandler.QueryType.RANGE, + "avg by(group) (http_requests_total{service='serviceA', layer='GENERAL'})", + List.of( + List.of( + new TimeValuePair(TIME_2023022010, "1.0"), + new TimeValuePair(TIME_2023022011, "2.0"), + new TimeValuePair(TIME_2023022012, "3.0") + ) + ), + List.of( + List.of( + new LabelValuePair("group", "g") + ) + ) + }, + { + "MetricsAggregationOpMax", + PromQLApiHandler.QueryType.RANGE, + "max (http_requests_total{service='serviceA', layer='GENERAL'}) by (group)", + List.of( + List.of( + new TimeValuePair(TIME_2023022010, "2.0"), + new TimeValuePair(TIME_2023022011, "3.0"), + new TimeValuePair(TIME_2023022012, "4.0") + ) + ), + List.of( + List.of( + new LabelValuePair("group", "g") + ) + ) + }, + { + "MetricsAggregationOpMin", + PromQLApiHandler.QueryType.RANGE, + "min (http_requests_total{service='serviceA', layer='GENERAL'}) by (group)", + List.of( + List.of( + new TimeValuePair(TIME_2023022010, "0.0"), + new TimeValuePair(TIME_2023022011, "1.0"), + new TimeValuePair(TIME_2023022012, "2.0") + ) + ), + List.of( + List.of( + new LabelValuePair("group", "g") + ) + ) + }, + { + "MetricsAggregationOpMinWithout", + PromQLApiHandler.QueryType.RANGE, + "min (http_requests_total{service='serviceA', layer='GENERAL'}) without (group)", + List.of( + List.of( + new TimeValuePair(TIME_2023022010, "0.0"), + new TimeValuePair(TIME_2023022011, "1.0"), + new TimeValuePair(TIME_2023022012, "2.0") + ), + List.of( + new TimeValuePair(TIME_2023022010, "2.0"), + new TimeValuePair(TIME_2023022011, "3.0"), + new TimeValuePair(TIME_2023022012, "4.0") + ) + ), + List.of( + List.of( + new LabelValuePair("service_instance_id", "a"), + new LabelValuePair("layer", "GENERAL") + ), + List.of( + new LabelValuePair("service_instance_id", "b"), + new LabelValuePair("layer", "GENERAL") + ) + ) + } + }); + } + @SneakyThrows @BeforeEach public void setup() { @@ -128,6 +231,10 @@ public class PromQLExprQueryVisitorTest { 0, DefaultScopeDefine.SERVICE ); + ValueColumnMetadata.INSTANCE.putIfAbsent("http_requests_total", "value", Column.ValueDataType.LABELED_VALUE, + 0, + DefaultScopeDefine.SERVICE + ); metricsQueryService = mock(MetricsQueryService.class); recordQueryService = mock(RecordQueryService.class); aggregationQueryService = mock(AggregationQueryService.class); @@ -138,6 +245,10 @@ public class PromQLExprQueryVisitorTest { Mockito.doReturn(mockMetricsValues()) .when(metricsQueryService) .readMetricsValues(any(MetricsCondition.class), any(Duration.class)); + + Mockito.doReturn(mockLabeledMetricsValues()) + .when(metricsQueryService) + .readLabeledMetricsValues(any(MetricsCondition.class), any(), any(Duration.class)); } private MetricsValues mockMetricsValues() { @@ -152,6 +263,30 @@ public class PromQLExprQueryVisitorTest { return values; } + private List<MetricsValues> mockLabeledMetricsValues() { + final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints(); + // {service_instance_id=a,group=g} 0, 1, 2 + MetricsValues values1 = new MetricsValues(); + values1.setLabel("{service_instance_id=a,group=g}"); + for (int i = 0; i < pointOfTimes.size(); i++) { + final KVInt kvInt = new KVInt(); + kvInt.setId(String.valueOf(pointOfTimes.get(i).getPoint())); + kvInt.setValue(i); + values1.getValues().addKVInt(kvInt); + } + + // {service_instance_id=b,group=g} 2, 3, 4 + MetricsValues values2 = new MetricsValues(); + values2.setLabel("{service_instance_id=b,group=g}"); + for (int i = 0; i < pointOfTimes.size(); i++) { + final KVInt kvInt = new KVInt(); + kvInt.setId(String.valueOf(pointOfTimes.get(i).getPoint())); + kvInt.setValue(i + 2); + values2.getValues().addKVInt(kvInt); + } + return List.of(values1, values2); + } + @ParameterizedTest(name = "{0}") @MethodSource("data") public void test(String name, @@ -182,4 +317,28 @@ public class PromQLExprQueryVisitorTest { Assertions.fail(); } } + + @ParameterizedTest(name = "{0}") + @MethodSource("aggregateData") + public void testAggregate(String name, + PromQLApiHandler.QueryType queryType, + String expression, + List<Object> wantResultValues, + List<Object> wantResultLabels) { + PromQLLexer lexer = new PromQLLexer(CharStreams.fromString(expression)); + CommonTokenStream tokens = new CommonTokenStream(lexer); + PromQLParser parser = new PromQLParser(tokens); + ParseTree tree = parser.expression(); + PromQLExprQueryVisitor visitor = new PromQLExprQueryVisitor( + metricsQueryService, recordQueryService, aggregationQueryService, duration, queryType); + ParseResult parseResult = visitor.visit(tree); + Assertions.assertEquals(ParseResultType.METRICS_RANGE, parseResult.getResultType()); + + MetricsRangeResult result = (MetricsRangeResult) parseResult; + Assertions.assertEquals(result.getMetricDataList().size(), wantResultValues.size()); + for (int i = 0; i < result.getMetricDataList().size(); i++) { + Assertions.assertEquals(result.getMetricDataList().get(i).getValues(), wantResultValues.get(i)); + Assertions.assertEquals(result.getMetricDataList().get(i).getMetric().getLabels(), wantResultLabels.get(i)); + } + } } diff --git a/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-by-p.yml b/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-by-p.yml new file mode 100644 index 0000000000..d2ca97a281 --- /dev/null +++ b/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-by-p.yml @@ -0,0 +1,46 @@ +# 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. + +status: success +data: + resultType: matrix + result: + {{- contains .data.result }} + - metric: + __name__: + p: 50 + values: + {{- contains .values }} + - - "{{ index . 0 }}" + - "{{ index . 1 }}" + {{- end}} + - metric: + __name__: + p: 75 + values: + {{- contains .values }} + - - "{{ index . 0 }}" + - "{{ index . 1 }}" + {{- end}} + - metric: + __name__: + p: 90 + values: + {{- contains .values }} + - - "{{ index . 0 }}" + - "{{ index . 1 }}" + {{- end}} + {{- end}} + diff --git a/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-without-p.yml b/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-without-p.yml new file mode 100644 index 0000000000..3a9d566087 --- /dev/null +++ b/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-without-p.yml @@ -0,0 +1,32 @@ +# 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. + +status: success +data: + resultType: matrix + result: + {{- contains .data.result }} + - metric: + __name__: + layer: GENERAL + scope: Service + service: e2e-service-consumer + values: + {{- contains .values }} + - - "{{ index . 0 }}" + - "{{ index . 1 }}" + {{- end}} + {{- end}} + diff --git a/test/e2e-v2/cases/promql/promql-cases.yaml b/test/e2e-v2/cases/promql/promql-cases.yaml index 51adce32cb..c32dd53ff3 100644 --- a/test/e2e-v2/cases/promql/promql-cases.yaml +++ b/test/e2e-v2/cases/promql/promql-cases.yaml @@ -74,6 +74,10 @@ cases: expected: expected/service-metric-matrix.yml - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 'query=service_percentile{service="e2e-service-consumer", layer="GENERAL", p="50,75,90"}&start='$(($(date +%s)-1800))'&end='$(date +%s) expected: expected/service-metric-labeled-matrix.yml + - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 'query=sum by (p) (service_percentile{service="e2e-service-consumer", layer="GENERAL", p="50,75,90"})&start='$(($(date +%s)-1800))'&end='$(date +%s) + expected: expected/service-metric-labeled-matrix-aggregate-by-p.yml + - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 'query=sum without (p) (service_percentile{service="e2e-service-consumer", layer="GENERAL", p="50,75,90"})&start='$(($(date +%s)-1800))'&end='$(date +%s) + expected: expected/service-metric-labeled-matrix-aggregate-without-p.yml - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 'query=service_cpm{layer="GENERAL",top_n="10", order="DES"}&start='$(($(date +%s)-1800))'&end='$(date +%s) expected: expected/service-metric-sort-matrix.yml ## instance