Skip to content

📘 日志系统最佳实践

—— CLI、客户端、服务器的三层架构

开发日志 / 架构记录 — 2025

在项目迭代过程中,我逐渐将日志系统整理为 三套互补的方案,分别用于 CLI 工具、客户端(游戏/编辑器)、服务器(生产环境)。
最终形成了 简洁、可维护、可扩展 的三层架构。

本文记录整个设计思路与最终结论,作为后续开发规范参考。


🔷 一、为什么需要三套日志库?

原因很简单:
不同运行环境,对日志的需求完全不同。

场景需求不适合合适
CLI(命令行工具)简单、按需启用、调试深度高loglevel、winstondebug
客户端(浏览器/游戏/编辑器)模块化、多 loggerName、轻量、可自定义前缀debug、winstonloglevel
服务器(生产环境)文件日志、JSON、数据库、轮转、异常捕获debug、loglevelwinston

最终决定:

  • CLI 用 debug
  • 客户端用 loglevel
  • 服务器用 Winston

这三者组合,正好覆盖所有需求,没有冗余。


🟦 二、CLI 层:使用 debug(按命名空间控制)

CLI 工具通常具备这些特点:

  • 运行一次
  • 输出量可能很大
  • 希望根据模块开关日志

这非常符合 debug 的哲学:

DEBUG=game:* node cli.js
DEBUG=build,core node script.js
DEBUG=*,-express:* node tool.js

特点:

  • ✔ 零配置
  • ✔ 按 namespace 精准控制
  • ✔ 关闭时无性能损耗(完全跳过)
  • ✔ 输出只到 stdout,不污染其它系统

这是 CLI 最强的选择,没有之一。


🟨 三、客户端:使用 loglevel(浏览器友好、可模块化)

客户端(游戏/工具/编辑器)需要:

  • 多模块日志(Game、Net、Editor)
  • 动态等级控制(warn、error、info、debug)
  • 在 VS Code Debug Console 上保持行号(通过 console 传递)
  • 可自定义彩色前缀、美观调试

loglevel 完全适配这些需求。

示例:

ts
const logger = loglevel.getLogger("game");
logger.warn("player disconnected");

并可通过 methodFactory 自定义前缀:

[warn] [game] Player lost connection

特点:

  • ✔ 模块化(每个系统一个 logger)
  • ✔ API 简单
  • ✔ 可在浏览器、Electron、工具全部复用
  • ✔ 不侵入 console 行为(可保持 VS Code 的行号)

这是客户端最优选择。


🟥 四、服务器:使用 Winston(结构化日志 + 文件/数据库)

服务器需要:

  • 写入文件(app.log、error.log)
  • 文件轮转(按天/按大小自动切分)
  • 写入数据库/ElasticSearch
  • JSON 格式
  • 捕获异常
    • uncaughtException
    • unhandledRejection
  • 多 transport 输出

Winston 做得最成熟:

ts
const logger = winston.createLogger({
  level: "info",
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: "logs/app.log" }),
    new winston.transports.File({ filename: "logs/error.log", level: "error" })
  ]
});

生产环境日志必须要 可靠可持久化,debug/loglevel 都做不到这一点。


🎯 五、三层结构如何互补?(关键表格总结)

层级理由
CLIdebugnamespace 精准开关;关闭时零损耗;命令行体验最好
客户端loglevel模块化、可自定义前缀、浏览器友好、可保留 VS Code 行号
服务器winston文件/DB 写入、JSON、轮转、生产级能力

这三者不重叠,各做各的强项,就是最佳实践。


🧱 六、统一思路(可选):Facade(门面层)

虽然使用了三套日志库,但可以对上层提供统一 API:

ts
log.debug(...)
log.info(...)
log.warn(...)
log.error(...)

并在入口注入:

  • CLI → debug
  • 客户端 → loglevel
  • 服务器 → Winston

这样使用上就完全一致。


✅ 七、最终结论

CLI = debug

客户端 = loglevel

服务器 = Winston

这是当前项目中最合理、最轻量、最好维护的日志体系。


风起江湖 · 资料站