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 0a1c214ce4 Fix range matrix and scalar binary operation in PromQL 
(#13616)
0a1c214ce4 is described below

commit 0a1c214ce495e9fbc6cd2d9e2a31b40f0482dadb
Author: weixiang1862 <[email protected]>
AuthorDate: Mon Dec 15 21:58:56 2025 +0800

    Fix range matrix and scalar binary operation in PromQL (#13616)
---
 docs/en/changes/changes.md                               |  1 +
 .../skywalking/oap/query/promql/rt/PromOpUtils.java      |  6 +++---
 .../oap/query/promql/rt/PromQLExprQueryVisitor.java      | 10 ++++++++--
 .../promql/rt/parser/PromQLExprQueryVisitorTest.java     | 16 ++++++++++++----
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index c81121fd8d..feba6cc0f5 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -10,6 +10,7 @@
 * Fix BrowserWebVitalsPerfData `clsTime` to `cls` and make it double type.
 * Init `log-mal-rules` at module provider start stage to avoid re-init for 
every LAL.
 * Fail fast if SampleFamily is empty after MAL filter expression.
+* Fix range matrix and scalar binary operation in PromQL.
 
 #### UI
 * Fix the missing icon in new native trace view.
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 bbef477d0c..dd1eb6aa84 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
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import 
org.apache.skywalking.mqe.rt.operation.aggregatelabels.AggregateLabelsFunc;
 import 
org.apache.skywalking.mqe.rt.operation.aggregatelabels.AggregateLabelsFuncFactory;
@@ -53,7 +54,7 @@ import static java.util.stream.Collectors.toList;
 
 public class PromOpUtils {
 
-    static MetricsRangeResult matrixScalarBinaryOp(MetricsRangeResult matrix, 
ScalarResult scalar, int opType) {
+    static MetricsRangeResult matrixScalarBinaryOp(MetricsRangeResult matrix, 
Function<Double, Double> rangeValueOp) {
         MetricsRangeResult result = new MetricsRangeResult();
         result.setResultType(ParseResultType.METRICS_RANGE);
         result.setRangeExpression(matrix.isRangeExpression());
@@ -64,8 +65,7 @@ public class PromOpUtils {
             List<TimeValuePair> newValues = 
metricData.getValues().stream().map(value -> {
                 double v = Double.parseDouble(value.getValue());
                 return new TimeValuePair(
-                    value.getTime(),
-                    formatDoubleValue(scalarBinaryOp(v, scalar.getValue(), 
opType))
+                    value.getTime(), formatDoubleValue(rangeValueOp.apply(v))
                 );
 
             }).collect(Collectors.toList());
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 fec0c99304..fefcf312c2 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
@@ -460,9 +460,15 @@ public class PromQLExprQueryVisitor extends 
PromQLParserBaseVisitor<ParseResult>
             scalarResult.setResultType(ParseResultType.SCALAR);
             return scalarResult;
         } else if (left.getResultType() == ParseResultType.METRICS_RANGE && 
right.getResultType() == ParseResultType.SCALAR) {
-            return matrixScalarBinaryOp((MetricsRangeResult) left, 
(ScalarResult) right, opType);
+            return matrixScalarBinaryOp(
+                (MetricsRangeResult) left,
+                rangeValue -> scalarBinaryOp(rangeValue, ((ScalarResult) 
right).getValue(), opType)
+            );
         } else if (left.getResultType() == ParseResultType.SCALAR && 
right.getResultType() == ParseResultType.METRICS_RANGE) {
-            return matrixScalarBinaryOp((MetricsRangeResult) right, 
(ScalarResult) left, opType);
+            return matrixScalarBinaryOp(
+                (MetricsRangeResult) right,
+                rangeValue -> scalarBinaryOp(((ScalarResult) left).getValue(), 
rangeValue, opType)
+            );
         } else if (left.getResultType() == ParseResultType.METRICS_RANGE && 
right.getResultType() == ParseResultType.METRICS_RANGE) {
             try {
                 return matrixBinaryOp((MetricsRangeResult) left, 
(MetricsRangeResult) right, opType);
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 961b1cc693..3982def2f1 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
@@ -111,6 +111,14 @@ public class PromQLExprQueryVisitorTest {
                 List.of(new TimeValuePair(TIME_2023022010, "100"), new 
TimeValuePair(TIME_2023022011, "101"),
                         new TimeValuePair(TIME_2023022012, "102"))
             },
+            {
+                "ScalarMetricsBinaryOp",
+                PromQLApiHandler.QueryType.RANGE,
+                "100 - service_cpm{service='serviceA', layer='GENERAL'}",
+                ParseResultType.METRICS_RANGE,
+                List.of(new TimeValuePair(TIME_2023022010, "100"), new 
TimeValuePair(TIME_2023022011, "99"),
+                        new TimeValuePair(TIME_2023022012, "98"))
+            },
             {
                 "MetricsBinaryOp",
                 PromQLApiHandler.QueryType.RANGE,
@@ -359,7 +367,7 @@ public class PromQLExprQueryVisitorTest {
                 break;
             case METRICS_RANGE:
                 MetricsRangeResult metricsRangeResult = (MetricsRangeResult) 
parseResult;
-                
Assertions.assertEquals(metricsRangeResult.getMetricDataList().get(0).getValues(),
 wantResultValues);
+                Assertions.assertEquals(wantResultValues, 
metricsRangeResult.getMetricDataList().get(0).getValues());
                 break;
             default:
                 Assertions.fail();
@@ -383,10 +391,10 @@ public class PromQLExprQueryVisitorTest {
         Assertions.assertEquals(ParseResultType.METRICS_RANGE, 
parseResult.getResultType());
 
         MetricsRangeResult result = (MetricsRangeResult) parseResult;
-        Assertions.assertEquals(result.getMetricDataList().size(), 
wantResultValues.size());
+        Assertions.assertEquals(wantResultValues.size(), 
result.getMetricDataList().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));
+            Assertions.assertEquals(wantResultValues.get(i), 
result.getMetricDataList().get(i).getValues());
+            Assertions.assertEquals(wantResultLabels.get(i), 
result.getMetricDataList().get(i).getMetric().getLabels());
         }
     }
 }

Reply via email to