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

zhangxiaowei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozhera.git


The following commit(s) were added to refs/heads/master by this push:
     new 4808a151 fix: Add try-catch to find out the reasons for the failure of 
span string parsing (#603)
4808a151 is described below

commit 4808a1515f3e353c53903847be43d50258f06e3f
Author: EricDing <[email protected]>
AuthorDate: Wed Sep 3 14:19:41 2025 +0800

    fix: Add try-catch to find out the reasons for the failure of span string 
parsing (#603)
    
    * fix: add SNAPSHOT repository
    
    * fix: Add try-catch to find out the reasons for the failure of span string 
parsing
    
    * fix: Fix the trace parsing issue
---
 ozhera-log/log-agent/pom.xml                       |   2 +-
 .../ozhera/log/agent/common/trace/TraceUtil.java   | 189 ++++++++++++---------
 2 files changed, 106 insertions(+), 85 deletions(-)

diff --git a/ozhera-log/log-agent/pom.xml b/ozhera-log/log-agent/pom.xml
index 69031a1f..5b974e5d 100644
--- a/ozhera-log/log-agent/pom.xml
+++ b/ozhera-log/log-agent/pom.xml
@@ -28,7 +28,7 @@ http://www.apache.org/licenses/LICENSE-2.0
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>log-agent</artifactId>
-    <version>2.2.7-SNAPSHOT</version>
+    <version>2.2.9-SNAPSHOT</version>
 
     <properties>
         <maven.compiler.source>21</maven.compiler.source>
diff --git 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/common/trace/TraceUtil.java
 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/common/trace/TraceUtil.java
index b16fb314..5a437fe6 100644
--- 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/common/trace/TraceUtil.java
+++ 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/common/trace/TraceUtil.java
@@ -89,22 +89,27 @@ public class TraceUtil {
     }
 
     public static TSpanData toTSpanData(String spanStr) {
-        // 步骤1优化:使用简单字符串替换代替正则表达式
-        String cleanSpanStr = spanStr.replace("\r\n", "");
-        
-        // 步骤2优化:使用 indexOf 代替 split 减少数组创建
-        String message = extractMessage(cleanSpanStr);
-        
-        // 步骤3优化:使用预分配大小的分割逻辑
-        String[] messageArray = splitMessage(message);
-        
-        // Bit check
-        if (messageArray.length != MessageUtil.COUNT) {
-            log.error("message count illegal : " + spanStr);
-            return null;
-        }
+        try {
+            // 步骤1优化:使用简单字符串替换代替正则表达式
+            String cleanSpanStr = spanStr.replace("\r\n", "");
 
-        return toTSpanData(messageArray);
+            // 步骤2优化:使用 indexOf 代替 split 减少数组创建
+            String message = extractMessage(cleanSpanStr);
+
+            // 步骤3优化:使用预分配大小的分割逻辑
+            String[] messageArray = splitMessage(message);
+
+            // Bit check
+            if (messageArray.length != MessageUtil.COUNT) {
+                log.error("message count illegal : " + spanStr);
+                return null;
+            }
+
+            return toTSpanData(messageArray);
+        } catch (Throwable t) {
+            log.error("Failed to convert span to TSpanData, spanStr={}", 
spanStr, t);
+        }
+        return null;
     }
 
     /**
@@ -116,13 +121,13 @@ public class TraceUtil {
             // 找到三重管道符,取后面的部分
             return spanStr.substring(tripleIndex + 5);
         }
-        
+
         int singleIndex = spanStr.indexOf(" | ");
         if (singleIndex != -1) {
             // 找到单管道符,取后面的部分
             return spanStr.substring(singleIndex + 3);
         }
-        
+
         // 兜底:如果都没找到,返回原字符串
         return spanStr;
     }
@@ -133,22 +138,22 @@ public class TraceUtil {
     private static String[] splitMessage(String message) {
         String delimiter = MessageUtil.SPLIT;
         int delimiterLength = delimiter.length();
-        
+
         // 预估分段数量,减少数组扩容
         List<String> parts = new ArrayList<>(MessageUtil.COUNT);
         int start = 0;
         int end;
-        
+
         while ((end = message.indexOf(delimiter, start)) != -1) {
             parts.add(message.substring(start, end));
             start = end + delimiterLength;
         }
-        
+
         // 添加最后一段
         if (start < message.length()) {
             parts.add(message.substring(start));
         }
-        
+
         return parts.toArray(new String[0]);
     }
 
@@ -188,36 +193,36 @@ public class TraceUtil {
         if (StringUtils.isEmpty(value)) {
             return value;
         }
-        
+
         // 如果不包含需要替换的字符,直接返回,避免不必要的处理
         if (!containsDecodeChars(value)) {
             return value;
         }
-        
+
         // 使用 StringBuilder 进行一次性替换,避免多次字符串创建
         return performOptimizedDecode(value);
     }
-    
+
     /**
      * 快速检查是否包含需要解码的字符序列
      */
     private static boolean containsDecodeChars(String value) {
         return value.indexOf('\\') != -1 || value.indexOf('#') != -1;
     }
-    
+
     /**
      * 执行优化的解码操作 - 使用字符级别的处理避免正则表达式
      */
     private static String performOptimizedDecode(String value) {
         StringBuilder result = new StringBuilder(value.length() + 20);
         char[] chars = value.toCharArray();
-        
+
         for (int i = 0; i < chars.length; i++) {
             if (chars[i] == '\\' && i + 1 < chars.length && chars[i + 1] == 
'\\') {
                 // 处理 \\ -> \\\\
                 result.append("\\\\\\\\");
                 i++; // 跳过下一个字符
-            } else if (chars[i] == '#' && i + 2 < chars.length && chars[i + 1] 
== '#') {
+            } else if (chars[i] == '#' && i + 1 < chars.length && chars[i + 1] 
== '#') {
                 // 处理 ## 开头的序列
                 String replacement = getReplacementForSequence(chars, i);
                 if (replacement != null) {
@@ -230,44 +235,60 @@ public class TraceUtil {
                 result.append(chars[i]);
             }
         }
-        
+
         return result.toString();
     }
-    
+
     /**
      * 获取字符序列的替换内容
      */
     private static String getReplacementForSequence(char[] chars, int start) {
-        if (start + 3 < chars.length) {
-            String sequence = new String(chars, start, Math.min(6, 
chars.length - start));
-            
-            // 精确匹配,避免正则表达式
-            if (sequence.startsWith("##r'")) return "\\\\\"";
-            if (sequence.startsWith("##n")) return "\\\\n";
-            if (sequence.startsWith("##r")) return "\\\\r";
-            if (sequence.startsWith("##t")) return "\\\\t";
-            if (sequence.startsWith("##tat")) return "\\\\tat";
-            if (sequence.startsWith("##'")) return "\\\\\"";
-        }
-        
+        if (start + 2 < chars.length) {
+            // 先检查最长的序列
+            if (start + 5 < chars.length) {
+                String sequence = new String(chars, start, 6);
+                if (sequence.equals("##tat")) return "\\\\tat";
+            }
+
+            // 检查4字符序列
+            if (start + 3 < chars.length) {
+                String sequence = new String(chars, start, 4);
+                if (sequence.equals("##r'")) return "\\\"";
+            }
+
+            // 检查3字符序列
+            String sequence = new String(chars, start, 3);
+            if (sequence.equals("##n")) return "\\\\n";
+            if (sequence.equals("##r")) return "\\\\r";
+            if (sequence.equals("##t")) return "\\\\t";
+            if (sequence.equals("##'")) return "\\\"";
+        }
+
         return null;
     }
-    
+
     /**
      * 获取匹配序列的长度
      */
     private static int getSequenceLength(char[] chars, int start) {
+        if (start + 5 < chars.length) {
+            String sequence = new String(chars, start, 6);
+            if (sequence.equals("##tat")) return 6;
+        }
+
         if (start + 3 < chars.length) {
-            String sequence = new String(chars, start, Math.min(6, 
chars.length - start));
-            
-            if (sequence.startsWith("##tat")) return 5;
-            if (sequence.startsWith("##r'")) return 4;
-            if (sequence.startsWith("##n")) return 3;
-            if (sequence.startsWith("##r")) return 3;
-            if (sequence.startsWith("##t")) return 3;
-            if (sequence.startsWith("##'")) return 3;
-        }
-        
+            String sequence = new String(chars, start, 4);
+            if (sequence.equals("##r'")) return 4;
+        }
+
+        if (start + 2 < chars.length) {
+            String sequence = new String(chars, start, 3);
+            if (sequence.equals("##n") || sequence.equals("##r") ||
+                sequence.equals("##t") || sequence.equals("##'")) {
+                return 3;
+            }
+        }
+
         return 1;
     }
 
@@ -369,38 +390,38 @@ public class TraceUtil {
             TAttributeKey attributeKey = toTAttributeKey(attrJson);
             Object value = attrJson.get("value");
 //            try {
-                TValue attributeValue = new TValue();
-                switch (attributeKey.getType()) {
-                    case LONG:
-                        if(value instanceof String){
-                            attributeValue.setLongValue(Long.valueOf((String) 
value));
-                        } else {
-                            attributeValue.setLongValue((Long) value);
-                        }
-                        break;
-                    case DOUBLE:
-                        if(value instanceof String){
-                            
attributeValue.setDoubleValue(Double.valueOf((String) value));
-                        } else {
-                            attributeValue.setDoubleValue((Double) value);
-                        }
-                        break;
-                    case STRING:
-                            
attributeValue.setStringValue(String.valueOf(value));
-                        break;
-                    case BOOLEAN:
-                        if(value instanceof String){
-                            
attributeValue.setBoolValue(Boolean.valueOf((String) value));
-                        } else {
-                            attributeValue.setBoolValue((Boolean) value);
-                        }
-                        break;
-                }
-                if (specialAttrMap != null && 
SPECIAL_TAG_KEYS.contains(attributeKey.getValue())) {
-                    specialAttrMap.put(attributeKey.getValue(), 
attributeValue);
-                }
-                ret.getKeys().add(attributeKey);
-                ret.getValues().add(attributeValue);
+            TValue attributeValue = new TValue();
+            switch (attributeKey.getType()) {
+                case LONG:
+                    if (value instanceof String) {
+                        attributeValue.setLongValue(Long.valueOf((String) 
value));
+                    } else {
+                        attributeValue.setLongValue((Long) value);
+                    }
+                    break;
+                case DOUBLE:
+                    if (value instanceof String) {
+                        attributeValue.setDoubleValue(Double.valueOf((String) 
value));
+                    } else {
+                        attributeValue.setDoubleValue((Double) value);
+                    }
+                    break;
+                case STRING:
+                    attributeValue.setStringValue(String.valueOf(value));
+                    break;
+                case BOOLEAN:
+                    if (value instanceof String) {
+                        attributeValue.setBoolValue(Boolean.valueOf((String) 
value));
+                    } else {
+                        attributeValue.setBoolValue((Boolean) value);
+                    }
+                    break;
+            }
+            if (specialAttrMap != null && 
SPECIAL_TAG_KEYS.contains(attributeKey.getValue())) {
+                specialAttrMap.put(attributeKey.getValue(), attributeValue);
+            }
+            ret.getKeys().add(attributeKey);
+            ret.getValues().add(attributeValue);
 //            } catch (Exception e) {
 //                log.error("Failed to add key '{}' value '{}' to attributes", 
attributeKey, value, e);
 //            }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to