日志系统(src/log.ts)

August 15, 2026 · View on GitHub

本文件解析结构化日志:记录格式、四通道分文件、按大小轮转,以及开发者在故障检修时的使用方式。

相关文档:架构总览


1. 记录格式

每条记录一行 JSON:

{ "ts": "2026-08-15T02:18:12.645Z", "level": "info", "cat": "qaq",
  "phase": "boot", "msg": "host + UI healthy; confirming for 20000ms",
  "profile": "web", ...meta }
  • ts:ISO-8601 UTC;level:info / warn / error;
  • cat:日志类别(qaq / rollback / ...);phase:可选阶段(boot / confirm / rollback / restart);
  • 自定义 meta 键值(profile、kind、action、snapDir 等)由调用方附加,undefined 值被剔除。
  • 单行 JSON 便于 Select-String / jq 等机器解析。

2. 四通道文件($DSH_HOME/.qaq/log/

文件内容用途
qaq.log全部(info + warn + error)主记录
error.log仅 warn / error快速 grep 问题
access.log崩溃审计轨迹启动结论、快照、回滚、重置、插件挂载、手动还原——状态变更的唯一完整轨迹
host.log被监督 dsh 的原始 stdout/stderr排查 dsh 自身输出;格式为 level ts 行内容

写入策略:

  • info/warn/error:写 qaq.log;warn/error 同时写 error.logaccess() 额外写 access.log 并镜像到 stdout。
  • host():子进程输出按行前缀时间戳写 host.log,并镜像到可见窗口(error 走 stderr,其余走 stdout)。

3. 轮转(按大小)

  • 阈值 ROTATE_BYTES = 256 KB;保留 KEEP_FILES = 5 份。
  • 触发:qaq.log → qaq.1.log → qaq.2.log …,超出 5 份删除最旧的。
  • 实现:sizes/lastCheck 做增量字节跟踪(约每 64KB 才 stat 一次),rotateFilerenameSync 递推 + 正则清理超龄副本。
  • 轮转是尽力而为的:任何异常都被吞掉,绝不影响业务。

4. 日志入口约定

const log = new Logger(home)          // home 为空/空白时回退 resolveDshHome()
log.info('...') / log.warn('...') / log.error('...', meta)
log.access('状态变更', { profile, action })   // 审计轨迹
log.host(chunk, 'stdout' | 'stderr')          // 子进程原始输出
log.in('rollback') / log.at('rollback')       // 派生类别/阶段日志

空 home 回退是硬性防线:new Logger('') 会把 .qaq 解析到 cwd 相对路径污染工作目录 (rollback.spec.ts 曾因模块顶层构造触发,已修复并加注释)。


5. 检修指引

场景看哪
启动结论 / 是否回滚access.log
报错与告警error.log
dsh 自身行为 / 红屏前的输出host.log
完整时间线qaq.log(含 phase 字段)
控制台内查看qaq console → [7]

示例排查(PowerShell):

# 最近的回滚
Select-String -Path "$HOME\.dsh\.qaq\log\access.log" -Pattern 'rolled back' | Select-Object -Last 5

# 某次启动的完整轨迹(按 phase 过滤)
Get-Content "$HOME\.dsh\.qaq\log\qaq.log" | ConvertFrom-Json | Where-Object { $_.phase -eq 'boot' }

6. 修改指南

  • 加通道 → 扩展 LogChannelfilePathFor,同步 access.log 表(本文件第 2 节)。
  • 改轮转阈值 → 只动 ROTATE_BYTES / KEEP_FILES 常量。
  • 加字段 → LogRecord 的索引签名已允许任意 meta;调用方直接传即可。
  • 测试:test/log.spec.ts 覆盖结构化格式、error 双写、access 通道、.in() 类别、轮转。