This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch groovy-replace
in repository https://gitbox.apache.org/repos/asf/skywalking.git

commit f0cdbd349cd2d1925d9c953bd06a984b1943bc4f
Author: Wu Sheng <[email protected]>
AuthorDate: Mon Mar 2 22:04:22 2026 +0800

    Extract LAL helper methods to LalRuntimeHelper static utility class
    
    Move 8 helper methods (getAt, toLong, toInt, toStr, toBool, isTruthy,
    tagValue, safeCall) from being duplicated in every generated class via
    addHelperMethods() to a shared LalRuntimeHelper in the rt package.
    Generated code now calls LalRuntimeHelper.toStr() etc. via FQCN.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../analyzer/v2/compiler/LALClassGenerator.java    | 124 ++++-----------------
 .../analyzer/v2/compiler/rt/LalRuntimeHelper.java  | 124 +++++++++++++++++++++
 2 files changed, 146 insertions(+), 102 deletions(-)

diff --git 
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALClassGenerator.java
 
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALClassGenerator.java
index ab4014eaed..8a396ce8bb 100644
--- 
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALClassGenerator.java
+++ 
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALClassGenerator.java
@@ -55,6 +55,8 @@ public final class LALClassGenerator {
         "org.apache.skywalking.oap.log.analyzer.v2.dsl.Binding";
     private static final String BINDING_PARSED =
         "org.apache.skywalking.oap.log.analyzer.v2.dsl.Binding.Parsed";
+    private static final String H =
+        
"org.apache.skywalking.oap.log.analyzer.v2.compiler.rt.LalRuntimeHelper";
     private static final String EXTRACTOR_SPEC =
         
"org.apache.skywalking.oap.log.analyzer.v2.dsl.spec.extractor.ExtractorSpec";
     private static final String SLOW_SQL_SPEC =
@@ -219,7 +221,6 @@ public final class LALClassGenerator {
         }
 
         ctClass.addConstructor(CtNewConstructor.defaultConstructor(ctClass));
-        addHelperMethods(ctClass);
 
         // Phase 4: Generate execute method referencing consumer fields
         final int[] counter = {0};
@@ -488,11 +489,11 @@ public final class LALClassGenerator {
         if (block.getValue() != null) {
             body.append("  _t.value(");
             if ("Long".equals(block.getValueCast())) {
-                body.append("(double) toLong(");
+                body.append("(double) ").append(H).append(".toLong(");
                 generateValueAccess(body, block.getValue());
                 body.append(")");
             } else if ("Integer".equals(block.getValueCast())) {
-                body.append("(double) toInt(");
+                body.append("(double) ").append(H).append(".toInt(");
                 generateValueAccess(body, block.getValue());
                 body.append(")");
             } else {
@@ -534,7 +535,7 @@ public final class LALClassGenerator {
             body.append(");\n");
         }
         if (block.getLatency() != null) {
-            body.append("  _t.latency(Long.valueOf(toLong(");
+            body.append("  
_t.latency(Long.valueOf(").append(H).append(".toLong(");
             generateValueAccess(body, block.getLatency());
             body.append(")));\n");
         }
@@ -586,13 +587,13 @@ public final class LALClassGenerator {
         switch (field.getFieldType()) {
             case LATENCY:
                 methodName = "latency";
-                sb.append("  _t.latency(Long.valueOf(toLong(");
+                sb.append("  
_t.latency(Long.valueOf(").append(H).append(".toLong(");
                 generateValueAccess(sb, field.getValue());
                 sb.append(")));\n");
                 return;
             case COMPONENT_ID:
                 methodName = "componentId";
-                sb.append("  _t.componentId(toInt(");
+                sb.append("  _t.componentId(").append(H).append(".toInt(");
                 generateValueAccess(sb, field.getValue());
                 sb.append("));\n");
                 return;
@@ -664,7 +665,7 @@ public final class LALClassGenerator {
         // Map FieldType to SampledTraceSpec methods
         switch (fa.getFieldType()) {
             case TIMESTAMP:
-                sb.append("  _t.latency(Long.valueOf(toLong(");
+                sb.append("  
_t.latency(Long.valueOf(").append(H).append(".toLong(");
                 generateValueAccess(sb, fa.getValue());
                 sb.append(")));\n");
                 break;
@@ -869,8 +870,6 @@ public final class LALClassGenerator {
                 ctClass));
         }
 
-        addHelperMethods(ctClass);
-
         final String method = "public void accept(Object arg) {\n"
             + "  " + info.castType + " _t = (" + info.castType + ") arg;\n"
             + info.body
@@ -991,85 +990,6 @@ public final class LALClassGenerator {
         }
     }
 
-    // ==================== Helper methods ====================
-
-    private void addHelperMethods(final CtClass ctClass) throws Exception {
-        ctClass.addMethod(CtNewMethod.make(
-            "private static Object getAt(Object obj, String key) {"
-            + "  if (obj == null) return null;"
-            + "  if (obj instanceof " + BINDING_PARSED + ")"
-            + "    return ((" + BINDING_PARSED + ") obj).getAt(key);"
-            + "  if (obj instanceof java.util.Map)"
-            + "    return ((java.util.Map) obj).get(key);"
-            + "  return " + BINDING_PARSED + ".getField(obj, key);"
-            + "}", ctClass));
-
-        ctClass.addMethod(CtNewMethod.make(
-            "private static long toLong(Object obj) {"
-            + "  if (obj instanceof Number) return ((Number) obj).longValue();"
-            + "  if (obj instanceof String) return Long.parseLong((String) 
obj);"
-            + "  return 0L;"
-            + "}", ctClass));
-
-        ctClass.addMethod(CtNewMethod.make(
-            "private static int toInt(Object obj) {"
-            + "  if (obj instanceof Number) return ((Number) obj).intValue();"
-            + "  if (obj instanceof String) return Integer.parseInt((String) 
obj);"
-            + "  return 0;"
-            + "}", ctClass));
-
-        ctClass.addMethod(CtNewMethod.make(
-            "private static String toStr(Object obj) {"
-            + "  return obj == null ? null : String.valueOf(obj);"
-            + "}", ctClass));
-
-        ctClass.addMethod(CtNewMethod.make(
-            "private static boolean toBool(Object obj) {"
-            + "  if (obj instanceof Boolean) return ((Boolean) 
obj).booleanValue();"
-            + "  if (obj instanceof String)"
-            + " return Boolean.parseBoolean((String) obj);"
-            + "  return obj != null;"
-            + "}", ctClass));
-
-        ctClass.addMethod(CtNewMethod.make(
-            "private static boolean isTruthy(Object obj) {"
-            + "  if (obj == null) return false;"
-            + "  if (obj instanceof Boolean)"
-            + " return ((Boolean) obj).booleanValue();"
-            + "  if (obj instanceof String)"
-            + " return !((String) obj).isEmpty();"
-            + "  if (obj instanceof Number)"
-            + " return ((Number) obj).doubleValue() != 0;"
-            + "  return true;"
-            + "}", ctClass));
-
-        // tag() value lookup using Binding
-        ctClass.addMethod(CtNewMethod.make(
-            "private static String tagValue("
-            + BINDING + " b, String key) {"
-            + "  java.util.List dl = b.log().getTags().getDataList();"
-            + "  for (int i = 0; i < dl.size(); i++) {"
-            + "    org.apache.skywalking.apm.network.common.v3"
-            + ".KeyStringValuePair kv = "
-            + "(org.apache.skywalking.apm.network.common.v3"
-            + ".KeyStringValuePair) dl.get(i);"
-            + "    if (key.equals(kv.getKey())) return kv.getValue();"
-            + "  }"
-            + "  return \"\";"
-            + "}", ctClass));
-
-        // Safe method call helper
-        ctClass.addMethod(CtNewMethod.make(
-            "private static Object safeCall(Object obj, String method) {"
-            + "  if (obj == null) return null;"
-            + "  if (\"toString\".equals(method)) return obj.toString();"
-            + "  if (\"trim\".equals(method)) return obj.toString().trim();"
-            + "  if (\"isEmpty\".equals(method))"
-            + " return Boolean.valueOf(obj.toString().isEmpty());"
-            + "  return obj.toString();"
-            + "}", ctClass));
-    }
-
     // ==================== Conditions ====================
 
     private void generateCondition(final StringBuilder sb,
@@ -1093,25 +1013,25 @@ public final class LALClassGenerator {
                     sb.append(")");
                     break;
                 case GT:
-                    sb.append("toLong(");
+                    sb.append(H).append(".toLong(");
                     generateValueAccessObj(sb, cc.getLeft(), null);
                     sb.append(") > ");
                     generateConditionValueNumeric(sb, cc.getRight());
                     break;
                 case LT:
-                    sb.append("toLong(");
+                    sb.append(H).append(".toLong(");
                     generateValueAccessObj(sb, cc.getLeft(), null);
                     sb.append(") < ");
                     generateConditionValueNumeric(sb, cc.getRight());
                     break;
                 case GTE:
-                    sb.append("toLong(");
+                    sb.append(H).append(".toLong(");
                     generateValueAccessObj(sb, cc.getLeft(), null);
                     sb.append(") >= ");
                     generateConditionValueNumeric(sb, cc.getRight());
                     break;
                 case LTE:
-                    sb.append("toLong(");
+                    sb.append(H).append(".toLong(");
                     generateValueAccessObj(sb, cc.getLeft(), null);
                     sb.append(") <= ");
                     generateConditionValueNumeric(sb, cc.getRight());
@@ -1134,7 +1054,7 @@ public final class LALClassGenerator {
                 ((LALScriptModel.NotCondition) cond).getInner());
             sb.append(")");
         } else if (cond instanceof LALScriptModel.ExprCondition) {
-            sb.append("isTruthy(");
+            sb.append(H).append(".isTruthy(");
             generateValueAccessObj(sb,
                 ((LALScriptModel.ExprCondition) cond).getExpr(),
                 ((LALScriptModel.ExprCondition) cond).getCastType());
@@ -1173,7 +1093,7 @@ public final class LALClassGenerator {
             sb.append((long) ((LALScriptModel.NumberConditionValue) cv)
                 .getValue()).append("L");
         } else if (cv instanceof LALScriptModel.ValueAccessConditionValue) {
-            sb.append("toLong(");
+            sb.append(H).append(".toLong(");
             generateValueAccessObj(sb,
                 ((LALScriptModel.ValueAccessConditionValue) cv).getValue(),
                 null);
@@ -1189,19 +1109,19 @@ public final class LALClassGenerator {
                                             final LALScriptModel.ValueAccess 
value,
                                             final String castType) {
         if ("String".equals(castType)) {
-            sb.append("toStr(");
+            sb.append(H).append(".toStr(");
             generateValueAccess(sb, value);
             sb.append(")");
         } else if ("Long".equals(castType)) {
-            sb.append("toLong(");
+            sb.append(H).append(".toLong(");
             generateValueAccess(sb, value);
             sb.append(")");
         } else if ("Integer".equals(castType)) {
-            sb.append("toInt(");
+            sb.append(H).append(".toInt(");
             generateValueAccess(sb, value);
             sb.append(")");
         } else if ("Boolean".equals(castType)) {
-            sb.append("toBool(");
+            sb.append(H).append(".toBool(");
             generateValueAccess(sb, value);
             sb.append(")");
         } else {
@@ -1213,7 +1133,7 @@ public final class LALClassGenerator {
                                          final LALScriptModel.ValueAccess 
value,
                                          final String castType) {
         if ("String".equals(castType)) {
-            sb.append("toStr(");
+            sb.append(H).append(".toStr(");
             generateValueAccess(sb, value);
             sb.append(")");
         } else {
@@ -1228,7 +1148,7 @@ public final class LALClassGenerator {
             if ("tag".equals(value.getFunctionCallName())
                     && !value.getFunctionCallArgs().isEmpty()) {
                 // tag("KEY") → tagValue(binding, "KEY")
-                sb.append("tagValue(binding, \"");
+                sb.append(H).append(".tagValue(binding, \"");
                 final String key = value.getFunctionCallArgs().get(0)
                     .getValue().getSegments().get(0);
                 sb.append(escapeJava(key)).append("\")");
@@ -1288,14 +1208,14 @@ public final class LALClassGenerator {
                 final String name =
                     ((LALScriptModel.FieldSegment) seg).getName();
                 // getAt() already handles null → null, so safe nav is free
-                current = "getAt(" + current + ", \""
+                current = H + ".getAt(" + current + ", \""
                     + escapeJava(name) + "\")";
             } else if (seg instanceof LALScriptModel.MethodSegment) {
                 final LALScriptModel.MethodSegment ms =
                     (LALScriptModel.MethodSegment) seg;
                 if (ms.isSafeNav()) {
                     // Safe navigation: null-safe method call
-                    current = "safeCall(" + current + ", \""
+                    current = H + ".safeCall(" + current + ", \""
                         + escapeJava(ms.getName()) + "\")";
                 } else {
                     if (ms.getArguments().isEmpty()) {
diff --git 
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/rt/LalRuntimeHelper.java
 
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/rt/LalRuntimeHelper.java
new file mode 100644
index 0000000000..cc5e0fccb9
--- /dev/null
+++ 
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/rt/LalRuntimeHelper.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.log.analyzer.v2.compiler.rt;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
+import org.apache.skywalking.oap.log.analyzer.v2.dsl.Binding;
+
+/**
+ * Static helper methods called by v2-generated {@code LalExpression} and 
consumer classes.
+ * Centralizes type coercion and field access logic that was previously 
duplicated
+ * into every generated class via {@code addHelperMethods()}.
+ */
+public final class LalRuntimeHelper {
+
+    private LalRuntimeHelper() {
+    }
+
+    public static Object getAt(final Object obj, final String key) {
+        if (obj == null) {
+            return null;
+        }
+        if (obj instanceof Binding.Parsed) {
+            return ((Binding.Parsed) obj).getAt(key);
+        }
+        if (obj instanceof Map) {
+            return ((Map) obj).get(key);
+        }
+        return Binding.Parsed.getField(obj, key);
+    }
+
+    public static long toLong(final Object obj) {
+        if (obj instanceof Number) {
+            return ((Number) obj).longValue();
+        }
+        if (obj instanceof String) {
+            return Long.parseLong((String) obj);
+        }
+        return 0L;
+    }
+
+    public static int toInt(final Object obj) {
+        if (obj instanceof Number) {
+            return ((Number) obj).intValue();
+        }
+        if (obj instanceof String) {
+            return Integer.parseInt((String) obj);
+        }
+        return 0;
+    }
+
+    public static String toStr(final Object obj) {
+        return obj == null ? null : String.valueOf(obj);
+    }
+
+    public static boolean toBool(final Object obj) {
+        if (obj instanceof Boolean) {
+            return ((Boolean) obj).booleanValue();
+        }
+        if (obj instanceof String) {
+            return Boolean.parseBoolean((String) obj);
+        }
+        return obj != null;
+    }
+
+    public static boolean isTruthy(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj instanceof Boolean) {
+            return ((Boolean) obj).booleanValue();
+        }
+        if (obj instanceof String) {
+            return !((String) obj).isEmpty();
+        }
+        if (obj instanceof Number) {
+            return ((Number) obj).doubleValue() != 0;
+        }
+        return true;
+    }
+
+    public static String tagValue(final Binding b, final String key) {
+        final List dl = b.log().getTags().getDataList();
+        for (int i = 0; i < dl.size(); i++) {
+            final KeyStringValuePair kv = (KeyStringValuePair) dl.get(i);
+            if (key.equals(kv.getKey())) {
+                return kv.getValue();
+            }
+        }
+        return "";
+    }
+
+    public static Object safeCall(final Object obj, final String method) {
+        if (obj == null) {
+            return null;
+        }
+        if ("toString".equals(method)) {
+            return obj.toString();
+        }
+        if ("trim".equals(method)) {
+            return obj.toString().trim();
+        }
+        if ("isEmpty".equals(method)) {
+            return Boolean.valueOf(obj.toString().isEmpty());
+        }
+        return obj.toString();
+    }
+}

Reply via email to