Support multiple function args. And add ThermodynamicIndicator
diff --git a/oal-parser/src/main/java/org/apache/skywalking/oap/server/core/Indicators.java b/oal-parser/src/main/java/org/apache/skywalking/oap/server/core/Indicators.java
index e73f366..4be82c9 100644
--- a/oal-parser/src/main/java/org/apache/skywalking/oap/server/core/Indicators.java
+++ b/oal-parser/src/main/java/org/apache/skywalking/oap/server/core/Indicators.java
@@ -34,6 +34,7 @@
REGISTER.put("p90", P90Indicator.class);
REGISTER.put("p75", P75Indicator.class);
REGISTER.put("p50", P50Indicator.class);
+ REGISTER.put("thermodynamic", ThermodynamicIndicator.class);
}
public static Class<? extends Indicator> find(String functionName) {
diff --git a/oal-parser/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/ThermodynamicIndicator.java b/oal-parser/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/ThermodynamicIndicator.java
new file mode 100644
index 0000000..d5a0a0f
--- /dev/null
+++ b/oal-parser/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/ThermodynamicIndicator.java
@@ -0,0 +1,129 @@
+/*
+ * 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.server.core.analysis.indicator;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.core.analysis.indicator.annotation.Arg;
+import org.apache.skywalking.oap.server.core.analysis.indicator.annotation.Entrance;
+import org.apache.skywalking.oap.server.core.analysis.indicator.annotation.IndicatorOperator;
+import org.apache.skywalking.oap.server.core.analysis.indicator.annotation.SourceFrom;
+import org.apache.skywalking.oap.server.core.storage.annotation.Column;
+
+/**
+ * Thermodynamic indicator represents the calculator for heat map.
+ *
+ * It groups the given collection of values by the given step and number of steps.
+ *
+ * A heat map (or heatmap) is a graphical representation of data where the individual values contained in a matrix are
+ * represented as colors.
+ *
+ * @author wusheng
+ */
+@IndicatorOperator
+public abstract class ThermodynamicIndicator extends Indicator {
+ protected static final String DETAIL_GROUP = "detail_group";
+ protected static final String STEP = "step";
+ protected static final String NUM_OF_STEPS = "num_of_steps";
+
+ @Getter @Setter @Column(columnName = STEP) private int step = 0;
+ @Getter @Setter @Column(columnName = NUM_OF_STEPS) private int numOfSteps = 0;
+ @Getter @Setter @Column(columnName = DETAIL_GROUP) private List<IntKeyLongValue> detailGroup = new ArrayList<>(30);
+
+ private Map<Integer, IntKeyLongValue> detailIndex;
+
+ /**
+ * @param value
+ * @param step the size of each step. A positive integer.
+ * @param maxNumOfSteps Steps are used to group incoming value.
+ *
+ * Data will be grouped in <br/>
+ *
+ * [0, step), [step, step * 2), ..., [step * (maxNumOfSteps - 1), step * maxNumOfSteps), [step * maxNumOfSteps,
+ * MAX)
+ */
+ @Entrance
+ public final void combine(@SourceFrom int value, @Arg int step, @Arg int maxNumOfSteps) {
+ if (this.step == 0) {
+ this.step = step;
+ }
+ if (this.numOfSteps == 0) {
+ this.numOfSteps = maxNumOfSteps + 1;
+ }
+
+ indexCheckAndInit();
+
+ int index = value / step;
+ if (index > maxNumOfSteps) {
+ index = numOfSteps;
+ }
+ IntKeyLongValue element = detailIndex.get(index);
+ if (element == null) {
+ element = new IntKeyLongValue();
+ element.setKey(index);
+ element.setValue(1);
+ addElement(element);
+ } else {
+ element.addValue(1);
+ }
+ }
+
+ @Override
+ public void combine(Indicator indicator) {
+ ThermodynamicIndicator thermodynamicIndicator = (ThermodynamicIndicator)indicator;
+ this.indexCheckAndInit();
+ thermodynamicIndicator.indexCheckAndInit();
+
+ thermodynamicIndicator.detailIndex.forEach((key, element) -> {
+ IntKeyLongValue existingElement = this.detailIndex.get(key);
+ if (existingElement == null) {
+ existingElement = new IntKeyLongValue();
+ existingElement.setKey(key);
+ existingElement.setValue(element.getValue());
+ addElement(element);
+ } else {
+ existingElement.addValue(element.getValue());
+ }
+ });
+ }
+
+ /**
+ * For Thermodynamic indicator, no single value field. Need to do nothing here.
+ */
+ @Override
+ public final void calculate() {
+
+ }
+
+ private void addElement(IntKeyLongValue element) {
+ detailGroup.add(element);
+ detailIndex.put(element.getKey(), element);
+ }
+
+ private void indexCheckAndInit() {
+ if (detailIndex == null) {
+ detailIndex = new HashMap<>();
+ detailGroup.forEach(element -> detailIndex.put(element.getKey(), element));
+ }
+ }
+}
diff --git a/oal-parser/src/test/resources/oal_test.oal b/oal-parser/src/test/resources/oal_test.oal
index 17634d2..b38b1ae 100644
--- a/oal-parser/src/test/resources/oal_test.oal
+++ b/oal-parser/src/test/resources/oal_test.oal
@@ -22,6 +22,8 @@
All_p75 = from(All.latency).p75(10);
All_p50 = from(All.latency).p50(10);
+All_heatmap = from(All.latency).thermodynamic(100, 20);
+
Service_Avg = from(Service.latency).longAvg();
ServiceInstance_RespTime= from(ServiceInstance.latency).longAvg();
diff --git a/oal-syntax/src/main/antlr4/org/apache/skywalking/oal/tool/grammar/OALParser.g4 b/oal-syntax/src/main/antlr4/org/apache/skywalking/oal/tool/grammar/OALParser.g4
index b225d3c..6e1f1f8 100644
--- a/oal-syntax/src/main/antlr4/org/apache/skywalking/oal/tool/grammar/OALParser.g4
+++ b/oal-syntax/src/main/antlr4/org/apache/skywalking/oal/tool/grammar/OALParser.g4
@@ -60,7 +60,7 @@
;
aggregateFunction
- : functionName LR_BRACKET (funcParamExpression | literalExpression)? RR_BRACKET
+ : functionName LR_BRACKET (funcParamExpression | (literalExpression (COMMA literalExpression)?))? RR_BRACKET
;
functionName