summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchaochaoc <[email protected]>2024-07-23 11:27:16 +0800
committerchaochaoc <[email protected]>2024-07-23 11:27:16 +0800
commitfaa70c31582fad4c7925d3cf16bb36b56241dc72 (patch)
tree14b7aaf63d477137a5de4bdb49514e561c7d9ac0
parentc2d05f2f9ed79533e26afadfb6152cd3a79192b4 (diff)
[GAL-625] feat: impl eval func use aviator-script
-rw-r--r--groot-core/pom.xml8
-rw-r--r--groot-core/src/main/java/com/geedgenetworks/core/expressions/EvalExecutor.java35
-rw-r--r--groot-core/src/main/java/com/geedgenetworks/core/expressions/SyntaxErrorException.java4
-rw-r--r--groot-core/src/main/java/com/geedgenetworks/core/udf/Eval.java4
-rw-r--r--groot-core/src/test/java/com/geedgenetworks/core/expressions/EvalExecutorTest.java140
5 files changed, 187 insertions, 4 deletions
diff --git a/groot-core/pom.xml b/groot-core/pom.xml
index 628670f..3243075 100644
--- a/groot-core/pom.xml
+++ b/groot-core/pom.xml
@@ -79,6 +79,10 @@
<artifactId>quartz</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.googlecode.aviator</groupId>
+ <artifactId>aviator</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.flink</groupId>
@@ -123,8 +127,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <source>9</source>
- <target>9</target>
+ <source>10</source>
+ <target>10</target>
</configuration>
</plugin>
diff --git a/groot-core/src/main/java/com/geedgenetworks/core/expressions/EvalExecutor.java b/groot-core/src/main/java/com/geedgenetworks/core/expressions/EvalExecutor.java
new file mode 100644
index 0000000..d3936f5
--- /dev/null
+++ b/groot-core/src/main/java/com/geedgenetworks/core/expressions/EvalExecutor.java
@@ -0,0 +1,35 @@
+package com.geedgenetworks.core.expressions;
+
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.Expression;
+import com.googlecode.aviator.exception.ExpressionRuntimeException;
+import com.googlecode.aviator.exception.ExpressionSyntaxErrorException;
+
+import java.util.Map;
+
+/**
+ * Eval Function Executor.
+ *
+ * @author chaoc
+ * @since 1.5
+ */
+public final class EvalExecutor implements Calc {
+
+ private final Expression script;
+
+ public EvalExecutor(String script) {
+ try {
+ AviatorEvaluator.validate(script);
+ this.script =
+ AviatorEvaluator.getInstance().compile(script);
+ } catch (ExpressionSyntaxErrorException
+ | ExpressionRuntimeException e) {
+ throw new SyntaxErrorException("Eval script syntax error. ", e);
+ }
+ }
+
+ @Override
+ public Object eval(final Map<String, Object> data) {
+ return script.execute(data);
+ }
+}
diff --git a/groot-core/src/main/java/com/geedgenetworks/core/expressions/SyntaxErrorException.java b/groot-core/src/main/java/com/geedgenetworks/core/expressions/SyntaxErrorException.java
index 5c2fe2c..f058615 100644
--- a/groot-core/src/main/java/com/geedgenetworks/core/expressions/SyntaxErrorException.java
+++ b/groot-core/src/main/java/com/geedgenetworks/core/expressions/SyntaxErrorException.java
@@ -13,4 +13,8 @@ public class SyntaxErrorException extends RuntimeException {
public SyntaxErrorException(String message) {
super(message);
}
+
+ public SyntaxErrorException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
diff --git a/groot-core/src/main/java/com/geedgenetworks/core/udf/Eval.java b/groot-core/src/main/java/com/geedgenetworks/core/udf/Eval.java
index 7f62858..e42e0be 100644
--- a/groot-core/src/main/java/com/geedgenetworks/core/udf/Eval.java
+++ b/groot-core/src/main/java/com/geedgenetworks/core/udf/Eval.java
@@ -5,7 +5,7 @@ import com.geedgenetworks.common.exception.GrootStreamRuntimeException;
import com.geedgenetworks.common.udf.UDF;
import com.geedgenetworks.common.udf.UDFContext;
import com.geedgenetworks.core.expressions.Calc;
-import com.geedgenetworks.core.expressions.codegen.CalcCodeConvertor;
+import com.geedgenetworks.core.expressions.EvalExecutor;
import com.geedgenetworks.common.Event;
import org.apache.flink.api.common.functions.RuntimeContext;
@@ -30,7 +30,7 @@ public class Eval implements UDF {
String expr = (String) udfContext.getParameters().get("value_expression");
List<String> outputField = udfContext.getOutput_fields();
output = outputField.get(0);
- calc = CalcCodeConvertor.convert(expr);
+ calc = new EvalExecutor(expr);
}
@Override
diff --git a/groot-core/src/test/java/com/geedgenetworks/core/expressions/EvalExecutorTest.java b/groot-core/src/test/java/com/geedgenetworks/core/expressions/EvalExecutorTest.java
new file mode 100644
index 0000000..e1e9924
--- /dev/null
+++ b/groot-core/src/test/java/com/geedgenetworks/core/expressions/EvalExecutorTest.java
@@ -0,0 +1,140 @@
+package com.geedgenetworks.core.expressions;
+
+import com.googlecode.aviator.exception.ExpressionRuntimeException;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class EvalExecutorTest {
+
+ private static Map<String, Object> origin;
+
+ @BeforeAll
+ public static void setUp() {
+ origin = new HashMap<>();
+ origin.put("common_schema_type", "RTP");
+ origin.put("common_sessions", 1);
+ origin.put("common_stream_dir", 3);
+ origin.put("common_vsys_id", 24);
+
+ origin.put("common_server_ip", "172.17.200.50");
+ origin.put("common_server_port", 36682);
+ origin.put("common_s2c_byte_num", 7570);
+ origin.put("common_s2c_pkt_num", 5);
+
+ origin.put("common_client_ip", "172.17.201.16");
+ origin.put("common_client_port", 42924);
+ origin.put("common_c2s_byte_num", 1834);
+ origin.put("common_c2s_pkt_num", 6);
+
+ origin.put("common_out_dest_mac", "02:fc:08:dc:92:d7");
+ origin.put("common_out_src_mac", "02:fc:08:dc:91:c3");
+ }
+
+ @Test
+ public void testValueExpression() throws Exception {
+ // constant
+ assertEquals(new EvalExecutor("'name'").eval(origin), "name");
+ assertEquals(new EvalExecutor("5").eval(origin), 5L);
+ assertEquals(new EvalExecutor("true").eval(origin), true);
+ assertEquals(new EvalExecutor("false").eval(origin), false);
+
+ // variable
+ assertEquals(new EvalExecutor("common_client_ip").eval(origin),
+ origin.get("common_client_ip"));
+ assertEquals(new EvalExecutor("common_client_port").eval(origin),
+ origin.get("common_client_port"));
+ }
+
+ @Test
+ public void testConditionExpression() throws Exception {
+ int commonClientPort = (int) origin.get("common_client_port");
+ int commonServerPort = (int) origin.get("common_server_port");
+ int commonC2sPktNum = (int) origin.get("common_c2s_pkt_num");
+ int commonS2cPktNum = (int) origin.get("common_s2c_pkt_num");
+ int commonC2sByteNum = (int) origin.get("common_c2s_byte_num");
+ int commonS2cByteNum = (int) origin.get("common_s2c_byte_num");
+ assertEquals(
+ new EvalExecutor("common_client_port > common_server_port " +
+ "? common_c2s_pkt_num : common_s2c_pkt_num").eval(origin),
+ commonClientPort > commonServerPort ? commonC2sPktNum : commonS2cPktNum);
+ assertEquals(
+ new EvalExecutor("common_client_port > common_server_port " +
+ "? 'C2S:' + common_c2s_pkt_num : 'S2C:' + common_s2c_pkt_num").eval(origin),
+ commonClientPort > commonServerPort ? "C2S:" + commonC2sPktNum : "S2C:" + commonS2cPktNum);
+ assertEquals(
+ new EvalExecutor("common_c2s_pkt_num > common_s2c_pkt_num " +
+ "&& common_c2s_byte_num > common_s2c_byte_num ? common_client_port : common_server_port").eval(origin),
+ commonC2sPktNum > commonS2cPktNum
+ && commonC2sByteNum > commonS2cByteNum ? commonClientPort : commonServerPort
+ );
+
+ }
+
+ @Test
+ public void testArithmeticExpression() throws Exception {
+ final Map<String, Object> map = Collections.emptyMap();
+ assertEquals(
+ 1L, new EvalExecutor("5 & 3").eval(map));
+ assertEquals(
+ 7L, new EvalExecutor("5 | 3").eval(map));
+ assertEquals(
+ 20L, new EvalExecutor("5 << 2").eval(map));
+ assertEquals(
+ 1L, new EvalExecutor("5 >> 2").eval(map));
+ assertEquals(
+ 8L, new EvalExecutor("5 + 3").eval(map));
+ assertEquals(
+ 2L, new EvalExecutor("5 - 3").eval(map));
+ assertEquals(
+ 15L, new EvalExecutor("5 * 3").eval(map));
+ assertEquals(
+ 2L, new EvalExecutor("5 / 2").eval(map));
+ assertEquals(
+ 2L, new EvalExecutor("5 % 3").eval(map));
+
+
+ final Map<String, Object> map1 = new HashMap<>();
+ map1.put("flags", 8);
+
+ assertEquals("B",
+ new EvalExecutor(" ( flags & 8 ) == 9 ? 'A' : 'B'").eval(map1));
+ assertEquals("A",
+ new EvalExecutor(" ( 5 | flags ) == 13 ? 'A' : 'B'").eval(map1));
+ }
+
+ @Test
+ public void testFieldArithmeticExpression() throws Exception {
+ assertEquals(1L,
+ new EvalExecutor("common_c2s_pkt_num - common_s2c_pkt_num").eval(origin));
+
+ assertEquals(17L, new EvalExecutor("common_c2s_pkt_num + 10 + 1").eval(origin));
+
+ }
+
+ @Test
+ public void testNullField() {
+ var evalExecutor = new EvalExecutor("( a > nil ? a : 0 ) + ( b > nil ? b : 10 )");
+ assertEquals(10L, evalExecutor.eval(origin));
+ }
+
+ @Test
+ public void testError() {
+ assertThrows(SyntaxErrorException.class,
+ () -> new EvalExecutor("1L"));
+ assertThrows(SyntaxErrorException.class,
+ () -> new EvalExecutor("2 = 3"));
+
+ final Map<String, Object> map = new HashMap<>(origin);
+ map.put("has_address", true);
+ var convert = new EvalExecutor("common_c2s_pkt_num + has_address");
+ assertThrows(ExpressionRuntimeException.class, () -> convert.eval(map));
+ }
+
+} \ No newline at end of file