From 39c116a608b126bb25c15c8ad5de24e7555cd1ed Mon Sep 17 00:00:00 2001 From: dengqichen Date: Sat, 13 Dec 2025 23:56:13 +0800 Subject: [PATCH] =?UTF-8?q?1.30=20k8s=20pods=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/deploy/utils/K8sLogParser.java | 76 +++++++++++++------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/utils/K8sLogParser.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/utils/K8sLogParser.java index 3403fed8..5d68fa45 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/utils/K8sLogParser.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/utils/K8sLogParser.java @@ -7,10 +7,13 @@ import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * K8S日志解析工具类 - * 基于Kubernetes Dashboard的引用点系统实现 + * 参考Kubernetes Dashboard实现 + * https://github.com/kubernetes/dashboard/blob/master/modules/api/pkg/resource/logs/logs.go */ @Slf4j public class K8sLogParser { @@ -18,9 +21,18 @@ public class K8sLogParser { private static final String NEWEST = "newest"; private static final String OLDEST = "oldest"; + /** + * K8s日志时间戳正则表达式 + * 匹配RFC3339格式:2025-12-13T23:27:18.124567890Z + * 或常规格式:2025-12-13 23:27:18.124 + */ + private static final Pattern TIMESTAMP_PATTERN = Pattern.compile( + "^(\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}\\.\\d+Z?)\\s" + ); + /** * 解析K8S原始日志为日志行列表 - * K8S日志格式:2025-12-13T23:00:01.123456789Z log content here + * 参考:logs.go ToLogLines函数 * * @param rawLogs 原始日志字符串 * @return 日志行列表 @@ -38,14 +50,14 @@ public class K8sLogParser { continue; } - // 查找第一个空格,分隔时间戳和内容 - int spaceIndex = line.indexOf(' '); - if (spaceIndex > 0 && spaceIndex < line.length() - 1) { - String timestamp = line.substring(0, spaceIndex); - String content = line.substring(spaceIndex + 1); + // 使用正则表达式提取时间戳 + Matcher matcher = TIMESTAMP_PATTERN.matcher(line); + if (matcher.find()) { + String timestamp = matcher.group(1); + String content = line.substring(matcher.end()); lines.add(new K8sLogLine(timestamp, content)); } else { - // 如果没有时间戳,使用空字符串作为时间戳 + // 没有时间戳的日志行 lines.add(new K8sLogLine("", line)); } } @@ -55,6 +67,7 @@ public class K8sLogParser { /** * 查找引用点在日志列表中的索引 + * 参考:logs.go getLineIndex函数 * * @param lines 日志行列表 * @param referenceTimestamp 引用点时间戳 @@ -74,28 +87,43 @@ public class K8sLogParser { } // 使用二分查找定位时间戳 - int index = Collections.binarySearch(lines, new K8sLogLine(referenceTimestamp, ""), - (a, b) -> a.getTimestamp().compareTo(b.getTimestamp())); + int matchingStartedAt = binarySearchTimestamp(lines, referenceTimestamp); - if (index >= 0) { - // 找到精确匹配 - return index; - } else { - // 未找到精确匹配,返回插入点 - int insertionPoint = -(index + 1); - // 返回最接近的索引 - if (insertionPoint >= lines.size()) { - return lines.size() - 1; - } - if (insertionPoint <= 0) { - return 0; - } - return insertionPoint; + if (matchingStartedAt < 0 || matchingStartedAt >= lines.size()) { + return -1; } + + return matchingStartedAt; + } + + /** + * 二分查找时间戳 + * + * @param lines 日志行列表 + * @param timestamp 目标时间戳 + * @return 第一个大于等于目标时间戳的索引 + */ + private static int binarySearchTimestamp(List lines, String timestamp) { + int left = 0; + int right = lines.size(); + + while (left < right) { + int mid = left + (right - left) / 2; + String midTimestamp = lines.get(mid).getTimestamp(); + + if (midTimestamp.compareTo(timestamp) < 0) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; } /** * 根据选择器切片日志 + * 参考:logs.go SelectLogs函数 * * @param lines 日志行列表 * @param selection 日志选择器