ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

NocoBase 插件开发指南:基于 Winston 封装的服务端日志系统全解

2026/9/17 19:29:35 拓冰建站 浏览量
NocoBase 插件开发指南:基于 Winston 封装的服务端日志系统全解 NocoBase 插件开发指南基于 Winston 封装的服务端日志系统全解【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobaseNocoBase 的服务端日志基于 Winston 二次封装将一次请求的运行过程划分为接口请求日志、系统运行日志和 SQL 执行日志三类。本文围绕插件开发场景完整讲解如何通过app.log、ctx.log、plugin.log打印符合约定字段的系统日志如何使用createSystemLogger、createLogger、app.createLogger、plugin.createLogger输出到自定义文件并结合nocobase/logger包的源码剖析日志级别、字段提取规则、输出格式logfmt/json/delimiter/console与传输器console/file/dailyRotateFile的实际实现帮助你写出可检索、可落盘、可分级的规范化日志。日志系统的三类分工NocoBase 默认将日志分为三类分别由不同的 logger 实例承载日志类型输出文件默认说明接口请求日志storage/logs/app/request.log记录 HTTP 请求由应用内部打印插件开发者通常无需关心系统运行日志storage/logs/app/system.log记录应用与插件的运行过程是插件开发者主要使用的日志SQL 执行日志storage/logs/app/sql.log记录数据库 SQL 执行级别为 debug由应用内部创建从源码结构看这三类 logger 在 application.ts 的initLogger方法中统一初始化系统日志通过createSystemLogger创建文件名system并开启seperateError将 error 级别单独输出请求日志通过createLogger创建文件名requestSQL 日志则复用this.createLogger({ filename: sql, level: debug })。这印证了文档中“接口请求日志和 SQL 执行日志由应用内部打印”的说法——插件开发者真正需要关心的是系统运行日志。默认打印方法app.log / ctx.log / plugin.logNocoBase 提供了系统运行日志的默认打印方法日志按规定字段格式化并同时输出到指定文件。三种使用方式如下// 默认打印方法 app.log.info(message); // 在中间件中使用 async function (ctx, next) { ctx.log.info(message); } // 在插件中使用 class CustomPlugin extends Plugin { async load() { this.log.info(message); } }字段约定module / submodule / method 的提取规则所有默认打印方法都遵循统一签名第一个参数为日志消息第二个参数为可选的 metadata 对象可以是任意键值对。其中module、submodule、method会被提取为单独的日志字段其余字段统一放入meta字段app.log.info(message, { module: module, submodule: submodule, method: method, key1: value1, key2: value2, }); // levelinfo timestamp2023-12-27 10:30:23 messagemessage modulemodule submodulesubmodule methodmethod meta{key1: value1, key2: value2} app.log.debug(); app.log.warn(); app.log.error();这条提取规则在 system-logger.ts 的SystemLoggerTransport.log方法中可以找到对应实现传输器从 Winston 的SPLAT附加参数中解构出module、submodule、method剩余键值对收集为meta同时还会自动附加app、reqId请求 ID便于链路追踪以及dataSourceKey默认main等上下文字段。若传入的 metadata 携带cause错误对象则cause.message与cause.stack会被作为一条独立日志写出方便排查异步错误链。此外SystemLogger接口为info / warn / error / debug / trace五个级别统一声明了(message, meta?)的调用签名这意味着app.log、ctx.log、this.log在任何级别上都支持同样的 metadata 传参方式。plugin.log 的实现细节插件中的this.log并非独立的日志实例而是应用日志的 child logger。从 plugin.ts 的源码可以看到get log() { return this.app.log.child({ reqId: this.app.context.reqId, module: this.name, }); }也就是说插件内每条日志都会自动带上module插件名字段和当前请求的reqId。因此在插件内部打日志时无需再手动指定module这正是上面 metadata 约定中module字段的典型来源。通过环境变量控制日志级别、格式与输出nocobase/logger包通过一组环境变量提供全局日志配置定义在 config.ts 中。了解这些配置有助于在开发、CI 和生产环境中调整日志行为环境变量作用默认值LOGGER_LEVEL日志级别APP_ENVdevelopment时为debug否则为infoLOGGER_TRANSPORT输出目标逗号分隔可选console/file/dailyRotateFileconsole,dailyRotateFileLOGGER_FORMAT打印格式可选console/logfmt/json/delimiter开发环境为console否则为jsonLOGGER_SILENT设为true时完全静默关闭LOGGER_MAX_SIZE单个日志文件滚动阈值字节file传输器约 20MB可由该变量覆盖LOGGER_MAX_FILES保留日志文件数量/周期file为 10 个dailyRotateFile为14d保留 14 天日志级别定义在 logger.ts 中采用 Winston 数值化级别数值越大越详细export const levels { trace: 4, debug: 3, info: 2, warn: 1, error: 0, };因此生产环境默认info级别时trace和debug日志不会输出开发环境默认debug插件开发期间可用this.log.debug(...)打印调试信息而不影响生产输出。另外有一个值得注意的实现细节createLogger检测到GITHUB_ACTIONS环境变量时会直接返回一个仅输出到控制台的 logger。从源码结构看这是为了在持续集成环境中避免产生日志文件、同时让错误信息可直接显示在 CI 日志里。输出到其他文件createSystemLogger如果想沿用系统默认的字段打印方法即module/submodule/method/meta提取规则但不希望输出到默认的系统日志文件可以用createSystemLogger创建一个自定义的系统日志实例import { createSystemLogger } from nocobase/logger; const logger createSystemLogger({ dirname: /pathto/, filename: xxx, seperateError: true, // 是否将 error 级别日志单独输出到 xxx_error.log });createSystemLogger的内部实现在 system-logger.ts。它构造了一个自定义传输器SystemLoggerTransport其工作机制是用createLogger创建一个主 logger 负责写出非 error 日志当seperateError为 true 时再创建一个名为${filename}_error、级别限定为error的独立 logger从而把错误日志分流到xxx_error.log文档示例注释中的默认行为与此一致接口注释标注seperateError默认值为true日志写入时按上述字段约定拆解 metadatalevel error的记录路由到 error logger其余走主 logger返回的 logger 通过 Proxy 改写了child方法使子 logger 能透传Error对象的stack、message和cause——因为原生 Winston 的子 logger 对error.cause支持不完整这一处理保证了错误堆栈信息在子 logger 场景下不丢失。自定义日志直接使用 Winston 原生方式如果不想使用系统提供的字段提取打印方法希望完全按 Winston 原生方式打日志可以通过nocobase/logger导出的createLogger创建import { createLogger } from nocobase/logger; const logger createLogger({ // options });options在原生winston.LoggerOptions的基础上进行了扩展完整类型见 logger.ts 的LoggerOptions接口dirname/filename—— 文件输出目录与文件名未显式指定transports时文件类传输器的目录默认解析为存储目录下的logstransports—— 可传字符串使用预置输出方式console、file、dailyRotateFile也可直接传winston.transport实例混合使用format—— 可传字符串使用预置打印格式logfmt、json、delimiter、console也可传winston.Logform.Format自定义。预置传输器的实际行为三种预置传输器的构造逻辑在 transports.ts 中console标准 Winston 控制台输出file固定文件名支持按LOGGER_MAX_SIZE默认约 20MB与LOGGER_MAX_FILES默认 10 个滚动dailyRotateFile按日期滚动依赖winston-daily-rotate-file默认保留14d。文件名中可使用%DATE%占位符未包含%DATE%或.log后缀时会自动补成${filename}_%DATE%.log形式。所有传输器都会自动叠加timestamp格式YYYY-MM-DD HH:mm:ss与所选 format无需重复配置时间戳。预置格式的实际行为四种预置格式实现在 format.ts格式输出示例/特征console带颜色的控制台输出[level]左对齐、message 填充到 44 列其余字段以keyvalue追加在后按 error 红 / warn 黄 / info 绿 / debug 蓝 / trace 青着色logfmt每行keyvalue key2value2对象值自动JSON.stringify便于 grep 与日志采集参见 logfmt 规范json标准 JSON 行输出适合 ELK 等集中式日志系统delimiter字段值以\|分隔连接若 message 中含分隔符会自动加引号并转义避免破坏列对齐默认行为上开发环境使用console格式、生产环境使用json格式见前文环境变量表。所有格式最终都会先经过sortFormat处理保证level字段排在最前。app.createLogger 与 plugin.createLogger按应用/插件组织日志目录在多应用场景下希望自定义日志输出到当前应用名称对应的目录时可以使用应用实例方法app.createLogger。从 application.ts 的源码可以看到它会在文件名前自动拼接当前应用名app.createLogger({ dirname: , filename: custom, // 输出到 /storage/logs/main/custom.log });// application.ts 中的实现节选 createLogger(options: LoggerOptions) { const { dirname } options; return createLogger({ ...options, dirname: getLoggerFilePath(path.join(this.name || main, dirname || )), }); }plugin.createLogger的使用场景和用法与app.createLogger相同内部直接委托给this.app.createLogger(options)见 plugin.ts。典型用法是为插件创建按天滚动的专属日志目录class CustomPlugin extends Plugin { async load() { const logger this.createLogger({ // 输出到 /storage/logs/main/custom-plugin/YYYY-MM-DD.log dirname: custom-plugin, filename: %DATE%.log, transports: [dailyRotateFile], }); } }这里transports: [dailyRotateFile]显式指定了按日期滚动配合%DATE%占位符日志会按天分文件存放在custom-plugin目录下便于按日期归档和检索插件产生的业务日志。小结与延伸阅读插件开发中优先使用this.log自动带module插件名与reqId并按约定传入module/submodule/method与业务字段其余字段会自动归入meta需要分流错误日志时用createSystemLogger并保留seperateError行为需要完全自定义 Winston 配置时用createLogger日志文件默认落在存储目录的logs/应用名/下级别、格式、传输方式均可通过LOGGER_*环境变量全局调整相关文档可继续参考Context 请求上下文、Plugin 插件、Telemetry 遥测、Middleware 中间件、服务端开发概述核心源码位于 packages/core/logger其中 system-logger.ts 实现了系统日志的字段提取与错误分流transports.ts 与 format.ts 分别定义了预置传输器和预置格式。【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考