生产环境如何根据日志级别动态控制输出?
最近在给公司项目做日志分级优化,想让开发环境输出所有日志,测试环境只留warn和error,生产环境只显示error。但按照网上的方法用process.env.NODE_ENV包裹console语句后,发现代码里到处都是这种判断,维护起来好麻烦。
尝试封装了个log工具类,用switch处理日志级别,但遇到个问题:if (level >= currentEnvLevel) { console.log(...args) }这种写法在生产环境遇到bug时,连错误堆栈都被过滤掉了。有没有更好的分级策略,既能按环境动态开关,又能保留关键错误信息?
附上现在混乱的代码:
export const log = (level, ...args) => {
const levels = { error: 3, warn: 2, info: 1 };
const envLevel = process.env.LOG_LEVEL || 'info';
if (levels[level] >= levels[envLevel]) {
switch(level) {
case 'error': console.error(...args); break;
case 'warn': console.warn(...args); break;
default: console.log(...args);
}
}
};
但发现当生产环境设置LOG_LEVEL=error时,意外捕获到的错误会因为没有调用log工具而直接输出,这该怎么统一管理?
首先封装一个更高效的log工具类,核心是通过环境变量控制日志级别,并且保留对未捕获异常的处理。代码如下:
这个方案有几个关键点。第一,
log函数会根据当前环境变量LOG_LEVEL动态判断是否输出日志,避免了代码里到处写判断。第二,重写了console.error方法,即使生产环境设置了只输出error级别的日志,也能保证所有错误信息被记录到stderr中。第三,监听了uncaughtException和unhandledRejection事件,统一处理未捕获的异常,防止意外错误丢失。效率更高的是,我们不需要为每个环境单独写一堆配置,只需要在启动服务时设置不同的
LOG_LEVEL值即可。比如开发环境用LOG_LEVEL=debug,测试环境用LOG_LEVEL=warn,生产环境用LOG_LEVEL=error。最后吐槽一句,这种日志分级管理确实麻烦,但一次性做好封装后面就省心了。记得测试下各种场景,尤其是生产环境的错误堆栈输出,别踩坑。
标准写法是用一个日志适配层把 console 给 wrap 住。关键是利用浏览器和 Node.js 都支持的 globalThis.console 的可配置性,在启动时根据环境替换掉原始方法。
你可以这样改:
然后你在项目入口处比如 app.js 开头加一行:
console.error = (...args) => logger.error(...args)这一步很重要,能捕获那些没走你 log 工具的裸 console 调用。当然更彻底的做法是在构建时通过 Webpack DefinePlugin 把所有
console.*替换成 logger 对应方法。另外提一嘴,生产环境只留 error 没问题,但建议加个临时开关机制,比如通过 URL 参数或 localStorage 强制提升日志级别,方便线上 debug。我们线上就靠
localStorage.debugLogLevel='warn'救过好多次。