Winston Logger写入MongoDB后Node.js进程无法自动终止问题
问题描述
测试Node.js日志库Winston时,将日志写入文件或输出到调试控制台均正常,但推送日志至MongoDB时,日志能正常传输,但进程无法自动终止,必须手动停止执行,且调试器未正常断开,没有其他传输方式结束时的"Waiting for the debugger to disconnect..."提示。
相关代码
prod-logger.js
const { format, createLogger, transports } = require('winston'); const { timestamp, combine, colorize, errors, json } = format; require('winston-mongodb'); require('dotenv').config() const db_name = process.env.MONGODBNAME function buildProdLogger(){ return createLogger({ format: combine( timestamp(), errors({stack: true}), json(), ), defaultMeta: { service: 'user-service' }, transports: new transports.MongoDB({ leve:'error', // 注意此处拼写错误:应为level db: db_name, options: { useUnifiedTopology: true }, collection: 'collection1' }) }); } module.exports = buildProdLogger;
logger/index.js
const buildDevLogger = require('./dev-logger'); const buildProdLogger = require('./prod-logger'); let logger = null; if (process.env.NODE_ENV === 'development'){ logger = buildDevLogger } else { logger = buildProdLogger } module.exports = logger();
index.js(主函数)
const logger = require('./logger'); logger.info('text info'); logger.warn('text warn'); logger.error('text error');
问题原因及解决方法
原因
Winston的MongoDB传输器会维持一个MongoDB连接池,且默认不会自动关闭。Node.js进程在存在活跃网络连接时,不会自动退出。你的代码执行完日志调用后,连接池仍处于打开状态,导致进程无法终止。
另外代码中存在拼写错误:transports.MongoDB配置里的leve应为level,该错误会导致日志级别规则不生效,但不直接影响进程退出。
解决方法
方法1:显式关闭MongoDB传输连接
在所有日志发送完成后,获取MongoDB传输器实例并调用其close方法,关闭连接池后退出进程:
const logger = require('./logger'); logger.info('text info'); logger.warn('text warn'); logger.error('text error'); // 获取MongoDB传输器实例 const mongoTransport = logger.transports.find(t => t.name === 'mongodb'); // 关闭连接并退出进程 mongoTransport.close(() => { process.exit(0); });
方法2:监听日志的finish事件
Winston的logger对象会在所有异步日志操作完成后触发finish事件,可在该事件中退出进程:
const logger = require('./logger'); logger.info('text info'); logger.warn('text warn'); logger.error('text error'); // 所有日志写入完成后关闭连接并退出 logger.on('finish', () => { const mongoTransport = logger.transports.find(t => t.name === 'mongodb'); mongoTransport.close(() => { process.exit(0); }); }); // 显式结束logger,触发finish事件 logger.end();
内容的提问来源于stack exchange,提问作者smartini
相关产品推荐
相关产品推荐

