跳到主要内容

dsh-stdio-logger

已验证

dsh-stdio-logger · v0.1.3 · MIT

dsh-desktop 日志桥插件:注册 cordis logger exporter,把宿主核心与全部插件的日志消息镜像到进程 stdout,供桌面壳捕获写入 logs/dsh-plugins.log

安装

dsh plugin add dsh-stdio-logger

用 dsh --profile default --dump-config 确认 layer 已生效 —— 参见安装指南。

源码

发布到 npm 但没有公开仓库。安装前请检查包内容。

标签

说明文档

dsh-stdio-logger

dsh 桌面壳的日志桥插件(host-only):注册 cordis logger exporter,把宿主核心与全部插件的结构化日志镜像到进程 stdout(桌面壳管道捕获写入 logs/dsh-plugins.log),并在 $DSH_HOME/logs/dsh-plugins.log 落一份持久文件,让不带壳的裸 dsh web 运行也有完整日志。

快速开始

本插件随桌面壳内置并自动安装(ensureBuiltinPlugins 标准链)。开发调试:

cd packages/dsh-stdio-logger
# 在插件目录内运行,file:$PWD 自动展开为当前绝对路径(必须 file: 而非 link:):
dsh plugin --profile web add file:$PWD

安装后重启 dsh web 进程生效;启动日志出现 attached; verbosity cap: warn 一行即 exporter 链路已接通。

官方 DSH 桌面端(0.1.7-rc.2 起)

官方壳不消费 logs/dsh-plugins.log、也不会替 profile 装本插件(asar 0 命中,见 ../../docs/VERIFICATION/OFFICIAL-0.1.7.md §1 与 §4.6), 所以官方端走 profile patch 直挂——本包 main 就是源码,不需要构建,也不需要 dsh plugin add:

# 追加到 <DSH_HOME>/profiles/desktop/cordis.patch.yml 末尾
- insert:
    - id: dsh-stdio-logger
      name: file:///<仓库绝对路径>/packages/dsh-stdio-logger/src/index.mjs
  • 改完先自检再重启(YAML 写坏会让整个 profile 起不来): node .dsh-scratch/plugin-fixes/validate-profile-patch.mjs
  • profile 启用 @deepseek-ai/dsh-hmr 时改 patch 即时生效,无需重启进程;否则重启一次。
  • 落盘位置:$DSH_HOME/logs/dsh-plugins.log(DSH_HOME 未设置时回退 ~/.dsh/logs/dsh-plugins.log)。 官方壳不接管 stdout,所以只有这个文件 sink 是持久日志。
  • 实测(2026-09-28):官方桌面端 + profile desktop,日志首行即 <本地ISO时间> [info] [dsh-stdio-logger] attached; verbosity cap: warn (DSH_STDIO_LOG_LEVEL); file sink -> <DSH_HOME>\logs\dsh-plugins.log; 挂载后立刻从静默变成可观测,例如 [error] [dsh-genui] TypeError: settingsCtx.settings.register is not a function 与 @linxin666/dsh-client-ui-skin-center 的 installSettingsSection 缺失报错。 第三方插件在官方端的具体适配缺陷清单见 ../../docs/VERIFICATION/OFFICIAL-0.1.7.md §9。

能力

项目 说明
双路输出 每行同时写 stdout 与文件;文件在 2 MB 处轮转为 .1.log(保留一份备份);Windows 上轮转改名失败时退化为原地截断并告警一次,日志始终有界
脱敏 token= / auth= / key= 等查询参数在写边界统一替换为 <redacted>,壳日志、本插件落盘与裸终端都看不到明文凭据
行格式 <本地ISO时间> [level] [plugin-name] message,与壳自身日志一致;多行消息(异常堆栈)每行都带完整前缀,避免壳侧重新盖章把堆栈帧误标为 [info]
冗长度 默认上限 warn(= error + info + warn),debug 需显式开启;exporter 层面抬高内核门禁,由本插件统一裁决
健壮性 stdout 管道断开(EPIPE)有常驻错误处理不崩进程;单行超过 10240 字符截断;文件/目录权限收紧(0o600 / 0o700);热路径无每行系统调用
自愈与可诊断 日志目录在运行中被删除后,下一行会自动重建目录并重试该行(不再整进程 ENOENT 失败);写盘失败每进程只告警一次,ENOSPC/EDQUOT 会明确指出「磁盘已满或超额」,stdout 始终不受影响

配置

环境变量 默认 说明
DSH_STDIO_LOG_LEVEL warn 输出冗长度上限:error / info / warn / debug
DSH_STDIO_LOG_FILE 1 0/false 关闭文件落盘(仅 stdout);显式路径则写到该文件;留空等价于未设置(用默认路径)

原理一句话

通过 ctx.logger.exporter 注册全树唯一的 exporter(levels.default=3 抬高 cordis 内核门禁),每条结构化消息按统一行格式盖章后先脱敏再写两个 sink;实现见 src/index.mjs。

文档

文档 内容
../../docs/PACKAGE-TEMPLATE.md 本仓库插件包统一规范

测试

node test/stdio-logger.test.js            # 冗长度/脱敏/多行/截断/占位符/env 语义/目录自愈/磁盘错误(9 条)
node test/integration-plugins-log.test.js # 真实 dsh web 后端全链路冒烟(需沙箱升级)
node test/isolated-install-cycle.test.js  # 隔离 DSH_HOME 安装/卸载循环 + 启动冒烟(需沙箱升级)

版本与兼容

包名 dsh-stdio-logger · MIT · 隔离环境实测基准 DSH 0.1.5-rc.2(标准链安装/卸载/启动挂载均通过);官方桌面端 0.1.7-rc.2 静态核查见 ../../docs/VERIFICATION/OFFICIAL-0.1.7.md——ctx.logger.exporter 与 levels.default 门控公式未变(机制可用),但官方壳不提供 logs/dsh-plugins.log 捕获,持久日志只靠本包文件 sink($DSH_HOME/logs/dsh-plugins.log)。

  • 0.1.3(当前):文档补丁(无代码改动)——同步官方 DSH 桌面端 0.1.7-rc.2 的接入说明:官方壳不消费 logs/dsh-plugins.log(本包 stdout sink 在官方端无消费者),官方端走 profile patch 直挂 file:///<仓库绝对路径>/packages/dsh-stdio-logger/src/index.mjs,持久日志只靠本包文件 sink($DSH_HOME/logs/dsh-plugins.log);ctx.logger.exporter 与 levels.default 的门控公式在 0.1.7-rc.2 未变,2026-09-28 在官方桌面端实测接通(首行即 [info] [dsh-stdio-logger] attached; verbosity cap: warn …,见 ../../docs/VERIFICATION/OFFICIAL-0.1.7.md §9.4)。
  • 0.1.2:日志目录自愈(运行中目录被删后下一行自动重建并重试,不再整进程 ENOENT 失败);磁盘类错误(ENOSPC/EDQUOT)在告警里明确指出「磁盘已满或超额」;stdout 错误监听改为每进程只注册一次(重复 apply / 重复 import 不再累积监听器)。
  • 0.1.1:默认冗长度上限 info → warn(旧默认把 warn 日志也丢掉);写边界统一脱敏;async EPIPE 常驻处理;单行 10240 截断;轮转失败原地截断;多行消息每行带统一前缀;热路径去每行系统调用;% 占位符只在首参为字符串时扫描;空 DSH_STDIO_LOG_FILE= 视同未设置;补齐 README/LICENSE。
  • 0.1.0:初版(exporter 注册 + stdout/文件双 sink + 2MB 轮转)。

元信息与文档结构遵循 docs/PACKAGE-TEMPLATE.md。