log4js 1.1.1升级至^6.4.0破坏性变更及clearAppenders报错排查
问题背景
- 项目将log4js依赖从1.1.1版本升级至^6.4.0版本后,仅Jenkins流水线环境触发运行异常,本地运行无报错,查阅版本差异文档未定位问题
- 原有日志模块初始化代码:
if (config.log.format === 'logstash') { log4js.clearAppenders() log4js.loadAppender('logstash', appender) log4js.addAppender(log4js.appenders.logstash()) } const logger = log4js.getLogger() logger.levels = config.log.level module.exports = logger
- 运行时抛出的核心错误信息:
log4js.clearAppenders()
^
TypeError: log4js.clearAppenders is not a function
at Object. (/usr/src/app/src/log/logger.js:6:10)
at Module._compile (internal/modules/cjs/loader.js:1156:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1176:10)
at Module.load (internal/modules/cjs/loader.js:1000:32)
at Function.Module._load (internal/modules/cjs/loader.js:899:14)
at Module.require (internal/modules/cjs/loader.js:1042:19)
at Module.require (/usr/src/app/node_modules/require-in-the-middle/index.js:43:24)
at require (internal/modules/cjs/helpers.js:77:18)
at Object. (/usr/src/app/index.js:4:13)
at Module._compile (internal/modules/cjs/loader.js:1156:30)
- 当前已完成的适配操作:将旧版日志级别写法
logger.setLevel(config.log.level)调整为logger.level=config.log.level,仍未解决报错。
跨大版本升级核心破坏性变更
log4js从v2版本开始做了全量API重构,v1版本的全局Appender操作API在v2及以上版本(包括6.4.0)已全部移除,代码中调用的三个方法均属于已废弃的v1 API:
log4js.clearAppenders():v1版本用于清空全局已注册的所有appender,v2+版本无对应全局方法log4js.loadAppender():v1版本用于手动加载第三方/自定义appender,v2+版本无需手动加载,直接在配置中声明即可log4js.addAppender():v1版本用于全局追加appender实例,v2+版本所有appender、category、日志级别配置统一通过log4js.configure()方法传入- 额外注意:原有代码中写的
logger.levels = config.log.level是错误写法,6.x版本日志级别属性为单数形式level,带复数s的写法会导致日志级别配置不生效
本地不报错、Jenkins报错的原因:本地大概率存在node_modules缓存残留,实际运行时加载的还是旧版本log4js文件,Jenkins为纯净依赖安装环境,安装的是完整6.x版本,因此会直接抛出API不存在的错误,本地删除node_modules和依赖锁文件重新安装即可复现问题。
修复代码
将零散的旧API调用全部替换为v6版本标准的统一配置写法,适配后的代码如下:
// 基础日志配置 const log4jsConfig = { appenders: { console: { type: 'console' } // 可根据实际需求保留/调整默认控制台输出 }, categories: { default: { appenders: ['console'], level: config.log.level } } } // 按需追加logstash appender配置 if (config.log.format === 'logstash') { log4jsConfig.appenders.logstash = { type: 'logstash', // 此处填入原有appender变量中的所有配置项,例如host、port、fields等 ...appender } log4jsConfig.categories.default.appenders.push('logstash') } // 统一初始化日志配置 log4js.configure(log4jsConfig) const logger = log4js.getLogger() module.exports = logger
注意:使用logstash appender需要提前安装对应的第三方appender依赖,例如log4js-logstash-appender,否则会报appender类型找不到的错误。
内容的提问来源于stack exchange,提问作者Cuciorva

