Files
aibis-dream/Docs/日志系统改进留档.md
T
dingyuntian 0265de117a docs(log-kit): 添加日志系统改进留档
- 记录背景、已完成内容、文件格式、平台默认配置
- 说明 GameLog 用法与后续待补足项
2026-07-08 15:21:05 +08:00

165 lines
6.2 KiB
Markdown
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.
# 日志系统改进留档
## 背景与目的
旧日志系统直接订阅 Unity 日志回调,把 `Debug.*` 输出同步写入文件。这个实现有几个明显问题:
- 每条日志同步 `WriteLine`,并且 `AutoFlush = true`,移动端写盘成本容易造成卡顿。
- Android 因性能问题被编译条件直接禁用文件日志,真机问题缺少可追踪依据。
- 日志格式只接近“控制台文本转储”,缺少等级、分类、场景、帧号、线程、会话等排查信息。
- 文件按天追加,同一天多次启动会混在一起,不利于定位一次具体测试或玩家反馈。
- `Application.logMessageReceivedThreaded` 可能从多线程进入,但旧实现直接操作同一个 `StreamWriter`,线程安全不足。
本次改进目标是建立一套可以在 PC 与 Android 都安全启用的轻量文件日志系统:降低写盘卡顿风险,保留 Unity 日志兼容入口,并为后续业务结构化日志打基础。
## 已完成内容
核心代码位于 `Assets/Scripts/Framework/LogKit/`
- `LogKit.cs`
- 保留运行时自动初始化入口。
- 继续订阅 `Application.logMessageReceivedThreaded`,捕获旧有 `Debug.Log/Warning/Error`
- 新增 `GameLog` 业务日志入口,支持按 `LogCategory` 分类输出。
- 新增 `LogLevel``LogCategory``LogEntry``LogFormatter`,把日志记录转换为结构化文本行。
- 应用失焦和退出时触发 flush,降低日志丢失概率。
- `FileLogger.cs`
- 从同步写文件改为线程安全队列 + 后台线程批量写入。
- 关闭每条日志 `AutoFlush`,改为批量 flush。
- 队列满时丢弃低优先级日志,并记录 dropped count。
- `Error` 及以上等级优先保留。
- 按 session 创建日志文件,并支持大小轮转、总大小/文件数量保留。
- 日志写入器内部异常静默降级,避免日志系统自身递归刷错误。
- `LogSettingsProfiles.cs`
- 将平台配置从 `LogKit.cs` 中抽离为轻量 C# profile。
- 不使用 JSON、StreamingAssets 或 ScriptableObject,避免额外资源加载和 Unity asset 依赖。
- 当前 profile 包括 `Editor``AndroidDevelopment``AndroidRelease``StandaloneDevelopment``StandaloneRelease`
## 日志文件与格式
日志目录仍使用 `ConstRef.LogFilePath`,即 `Application.persistentDataPath/LogFile`
文件按启动会话生成,命名格式类似:
```text
20260708_153012_android_v1.2.0_session-abcd1234.log
```
单行日志包含:
```text
timestamp | level | category | scene | frame | thread | context | message | stack
```
说明:
- `timestamp` 使用 UTC ISO 格式。
- `category` 可区分 Unity 捕获日志和业务系统日志。
- 非主线程日志不会读取 Unity 场景和帧号,避免在线程回调中访问 Unity 主线程 API。
- 普通日志默认不写堆栈;`Error/Exception/Assert` 写入堆栈。
## 平台默认配置
当前配置集中在 `LogSettingsProfiles.cs`
### Editor
- 默认不写文件日志。
- 仍保留 Unity Console 的正常输出。
### Android Development
- 文件日志启用。
- 最低等级:`Info`
- 队列容量:`1024`
- 批量写入:`64` 条。
- Flush 间隔:`1500ms`
- 单文件上限:`5MB`
- 总保留上限:`30MB`
- Session 文件保留:`6` 个。
### Android Release
- 文件日志启用。
- 最低等级:`Warning`
- Console 最低等级:`Warning`
- 其余写入参数与 Android Development 保持一致。
### Standalone Development / Release
- 文件日志启用。
- Development 最低等级:`Info`Console 最低等级:`Debug`
- Release 最低等级:`Info`Console 最低等级:`Info`
- 队列容量:`2048`
- 批量写入:`128` 条。
- Flush 间隔:`1000ms`
- 单文件上限:`10MB`
- 总保留上限:`100MB`
- Session 文件保留:`20` 个。
## 如何使用
旧代码中的 `Debug.Log/Warning/Error` 不需要立刻迁移,仍会被捕获到文件日志。
新代码或关键链路建议使用 `GameLog`
```csharp
GameLog.Info(LogCategory.Save, "Auto save completed", "slot=0");
GameLog.Warn(LogCategory.Resource, "Addressable load slow", "key=Scene/ClinicOut");
GameLog.Error(LogCategory.Yarn, "Node missing", "node=Start");
```
优先迁移高价值排查链路,而不是一次性替换全项目日志:
- 存档/读档:`SaveRestoreOrchestrator``SaveSystem`
- 对话:`DialogController`、Yarn node 进入/退出
- 资源:`ResourceSystem``SceneResourceLoader`
- 场景:`SceneLoader`
- 维修系统入口:`FixSystemCenter`
## 已验证内容
本次实现后已执行:
```bash
git diff --check -- Assembly-CSharp.csproj Assets/Scripts/Framework/LogKit
dotnet build Assembly-CSharp.csproj --no-restore
```
结果:
- 空白检查通过。
- `Assembly-CSharp.csproj` 构建通过,0 个错误。
- 构建中的 warning 为项目既有 warning,与日志系统改动无关。
## 仍需补足
后续建议按优先级补足以下内容:
1. Android 真机压测
- 在 Android Development build 中压测高频 `Debug.Log`
- 对比启用日志前后的帧率和卡顿尖刺。
- 验证切后台、返回、退出时日志能正常 flush。
2. 关键业务链路迁移到 `GameLog`
- 先迁移 Save、Resource、Dialog、Scene 这些排查价值最高的系统。
- 不建议批量替换所有旧 `Debug.Log`,避免制造无意义 diff。
3. 重复日志限流
- 当前已有队列满时低等级丢弃机制。
- 仍可补充同一 message 短时间重复出现时的合并策略,减少高频系统刷屏。
4. 日志导出入口
- 增加获取当前日志目录或当前 session 日志路径的 API。
- 后续可接入设置界面或测试菜单,方便测试人员导出日志。
5. 配置开关扩展
- 当前 profile 是代码内固定配置。
- 如果未来测试需要临时打开 Release `Info` 日志,可考虑增加启动参数、调试菜单或本地轻量覆盖开关。
6. Unity 工程文件同步
- 本次为了命令行构建验证,手动把 `LogSettingsProfiles.cs` 加入了 `Assembly-CSharp.csproj`
- Unity 重新生成工程文件时可能覆盖 `.csproj`,这是 Unity 生成文件的正常行为;源码和 `.meta` 才是长期留档重点。