Files
MRCC/launcher/PCL-CE/Plain Craft Launcher 2/Modules/Minecraft/CrashAnalysis/Logs/CrashLogCollector.cs
T
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

127 lines
4.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.IO;
using PCL.Core.App;
using PCL.Core.Logging;
namespace PCL;
internal sealed class CrashLogCollector(CrashAnalysisContext context)
{
public void Collect(string versionPathIndie, IList<string>? latestLog)
{
LogWrapper.Info("Crash", "步骤 1:收集日志文件");
var possibleLogs = _FindPossibleLogFiles(versionPathIndie)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var recentLogs = possibleLogs.Where(IsRecentNonEmptyFile).ToList();
if (recentLogs.Count == 0)
LogWrapper.Info("Crash", "未发现可能可用的日志文件");
foreach (var filePath in recentLogs)
TryAddLogFile(filePath, "读取可能的崩溃日志文件失败");
AddCapturedOutput(latestLog);
LogWrapper.Info("Crash", "步骤 1:收集日志文件完成,收集到 " + context.RawFiles.Count + " 个文件");
}
private static IEnumerable<string> _FindPossibleLogFiles(string versionPathIndie)
{
var possibleLogs = new List<string>();
try
{
var dirInfo = new DirectoryInfo(Path.Combine(versionPathIndie, "crash-reports"));
if (dirInfo.Exists)
possibleLogs.AddRange(dirInfo.EnumerateFiles().Select(file => file.FullName));
}
catch (Exception ex)
{
LogWrapper.Warn(ex, "Crash", "收集 Minecraft 崩溃日志文件夹下的日志失败");
}
try
{
var rootDirectory = new DirectoryInfo(versionPathIndie).Parent?.Parent;
if (rootDirectory is not null && rootDirectory.Exists)
possibleLogs.AddRange(
rootDirectory.EnumerateFiles()
.Where(file => file.Extension == ".log")
.Select(file => file.FullName));
}
catch (Exception ex)
{
LogWrapper.Warn(ex, "Crash", "收集 Minecraft 主文件夹下的日志失败");
}
try
{
var instanceDirectory = new DirectoryInfo(versionPathIndie);
if (instanceDirectory.Exists)
possibleLogs.AddRange(
instanceDirectory.EnumerateFiles()
.Where(file => file.Extension == ".log")
.Select(file => file.FullName));
}
catch (Exception ex)
{
LogWrapper.Warn(ex, "Crash", "收集 Minecraft 隔离文件夹下的日志失败");
}
possibleLogs.Add(Path.Combine(versionPathIndie, "logs", "latest.log"));
var launchScript = CrashFileIo.ReadText(Path.Combine(Basics.ExecutableDirectory, "PCL", "LatestLaunch.bat"));
if (launchScript.Contains("-Dlog4j2.formatMsgNoLookups=false", StringComparison.OrdinalIgnoreCase))
possibleLogs.Add(Path.Combine(versionPathIndie, "logs", "debug.log"));
return possibleLogs;
}
private static bool IsRecentNonEmptyFile(string filePath)
{
try
{
var info = new FileInfo(filePath);
if (!info.Exists || info.Length <= 0L)
return false;
var ageMinutes = Math.Abs((info.LastWriteTime - DateTime.Now).TotalMinutes);
if (ageMinutes >= 3d)
return false;
LogWrapper.Info("Crash", "可能可用的日志文件:" + filePath + "" + Math.Round(ageMinutes, 1) + " 分钟)");
return true;
}
catch (Exception ex)
{
LogWrapper.Warn(ex, "Crash", "确认崩溃日志时间失败(" + filePath + "");
return false;
}
}
private void TryAddLogFile(string filePath, string errorMessage)
{
try
{
context.RawFiles.Add(
new CrashLogEntry(filePath, CrashFileIo.ReadText(filePath).Split("\r\n".ToCharArray())));
}
catch (Exception ex)
{
LogWrapper.Warn(ex, "Crash", errorMessage + "" + filePath + "");
}
}
private void AddCapturedOutput(IList<string>? latestLog)
{
if (latestLog is null || !latestLog.Any())
return;
var rawOutput = string.Join("\r\n", latestLog);
LogWrapper.Info("Crash", "以下为游戏输出的最后一段内容:" + "\r\n" + rawOutput);
var rawOutputPath = Path.Combine(context.TempFolder, "RawOutput.log");
CrashFileIo.WriteText(rawOutputPath, rawOutput);
context.RawFiles.Add(new CrashLogEntry(rawOutputPath, latestLog.ToArray()));
latestLog.Clear();
}
}