fix
Some checks failed
Docker Build & Deploy / Build Docker Image (push) Failing after 6s
Docker Build & Deploy / Deploy to Production (push) Has been skipped

This commit is contained in:
2026-01-01 11:58:21 +08:00
parent 0444218898
commit c1aa4df4f3
11 changed files with 442 additions and 165 deletions

View File

@@ -120,11 +120,10 @@ public class LogController(ILogger<LogController> logger) : ControllerBase
/// <summary>
/// 合并多行日志(已废弃,现在在流式读取中处理)
/// </summary>
[Obsolete("Use ReadLogsStreamAsync instead")]
private List<string> MergeMultiLineLog(string[] lines)
{
var mergedLines = new List<string>();
var currentLog = new System.Text.StringBuilder();
var currentLog = new StringBuilder();
// 日志行开始的正则表达式
var logStartPattern = new System.Text.RegularExpressions.Regex(
@@ -175,9 +174,11 @@ public class LogController(ILogger<LogController> logger) : ControllerBase
{
// 日志格式示例: [2025-12-29 16:38:45.730 +08:00] [INF] Message here
// 使用正则表达式解析
// 使用 Singleline 模式使 '.' 可以匹配换行,这样 multi-line 消息可以被完整捕获。
var match = System.Text.RegularExpressions.Regex.Match(
line,
@"^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [+-]\d{2}:\d{2})\] \[([A-Z]{3})\] (.*)$"
@"^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [+-]\d{2}:\d{2})\] \[([A-Z]{2,5})\] ([\s\S]*)$",
System.Text.RegularExpressions.RegexOptions.Singleline
);
if (match.Success)
@@ -214,82 +215,30 @@ public class LogController(ILogger<LogController> logger) : ControllerBase
string? searchKeyword,
string? logLevel)
{
var filteredEntries = new List<LogEntry>();
var currentLog = new System.Text.StringBuilder();
var logStartPattern = new System.Text.RegularExpressions.Regex(
@"^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [+-]\d{2}:\d{2}\]");
// 简化:一次性读取所有行,合并多行日志,过滤并在内存中分页
var allLines = await ReadAllLinesAsync(path);
// 计算需要读取的最大条目数取最近的N条日志用于倒序分页
// 由于日志倒序显示,我们读取足够的数据以覆盖当前页
var maxEntriesToRead = pageIndex * pageSize + pageSize; // 多读一页用于判断是否有下一页
// 合并多行日志为独立条目
var merged = MergeMultiLineLog(allLines);
using var fileStream = new FileStream(
path,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite);
using var streamReader = new StreamReader(fileStream);
string? line;
var readCount = 0;
while ((line = await streamReader.ReadLineAsync()) != null)
var parsed = new List<LogEntry>();
foreach (var line in merged)
{
if (string.IsNullOrWhiteSpace(line))
continue;
// 检查是否是新的日志条目
if (logStartPattern.IsMatch(line))
var entry = ParseLogLine(line);
if (entry != null && PassFilter(entry, searchKeyword, logLevel))
{
// 处理之前累积的日志
if (currentLog.Length > 0)
{
var logEntry = ParseLogLine(currentLog.ToString());
if (logEntry != null && PassFilter(logEntry, searchKeyword, logLevel))
{
filteredEntries.Add(logEntry);
readCount++;
// 如果已读取足够数据,提前退出
if (readCount >= maxEntriesToRead)
{
break;
}
}
currentLog.Clear();
}
currentLog.Append(line);
}
else
{
// 这是上一条日志的延续
if (currentLog.Length > 0)
{
currentLog.Append('\n').Append(line);
}
parsed.Add(entry);
}
}
// 处理最后一条日志(如果循环正常结束或刚好在日志边界退出
if (currentLog.Length > 0 && readCount < maxEntriesToRead)
{
var logEntry = ParseLogLine(currentLog.ToString());
if (logEntry != null && PassFilter(logEntry, searchKeyword, logLevel))
{
filteredEntries.Add(logEntry);
}
}
// 倒序(最新在前
parsed.Reverse();
// 倒序排列(最新的在前面)
filteredEntries.Reverse();
var total = parsed.Count;
var skip = Math.Max(0, (pageIndex - 1) * pageSize);
var pagedData = parsed.Skip(skip).Take(pageSize).ToList();
// 计算分页
var skip = (pageIndex - 1) * pageSize;
var pagedData = filteredEntries.Skip(skip).Take(pageSize).ToList();
// total 返回 -1 表示未知(避免扫描整个文件)
// 前端可以根据返回数据量判断是否有下一页
return (pagedData, -1);
return (pagedData, total);
}
/// <summary>