Winston Logger自定义CustomTransport回调仅触发一次及WebSocket通信异常问题排查
解决方案:Winston自定义Transport与WebSocket发送问题
首先,从你的描述来看,WebSocket连接在关闭心跳后已经稳定,而仅能发送一次日志的核心问题出在Winston自定义Transport的实现上,结合你提供的代码,我整理了几个关键修复点:
1. 修复Winston Transport的异步处理逻辑
Winston的Transport是基于异步设计的,如果你没有在log方法中调用完成回调,Winston可能会认为日志任务未完成,从而停止触发后续的日志事件。修改你的CustomTransport实现:
const { Transport } = require('winston'); class CustomTransport extends Transport { // 必须调用父类构造函数,传入配置项 constructor(options) { super(options); } // log方法需要接收info和done回调参数 log(info, done) { // 执行WebSocket发送逻辑 sendToWebsocket(info); // 调用done告知Winston日志已处理完成 setImmediate(done); } }
2. 修正Stomp.send方法的参数错误
你之前的sendLog方法存在参数传递错误:Stomp.js的send方法签名是send(destination, headers, body),你直接把log.message作为第二个参数(headers),这会导致消息体为空,后端可能无法正确解析,甚至引发异常。调整为正确的格式:
export const sendLog = log => { console.log("TRYING TO SEND", log); if (loggingStompClient) { try { loggingStompClient.send("/app/logging", {}, JSON.stringify(log.message)); } catch (err) { console.error('Failed to send log via WebSocket:', err); } } };
3. 确认Winston日志级别匹配
检查你调用logger.info()(或其他级别方法)的地方,确保日志级别不低于你在logger配置中设置的level: 'info'。如果你的日志是用logger.debug()发送的,而级别设为info,则不会触发Transport的log方法。
4. 添加Winston异常监听排查问题
虽然你设置了handleExceptions: true,但可以添加错误监听来排查是否有未捕获的异常导致Transport停止工作:
logger.on('error', (err) => { console.error('Winston logger error:', err); });
5. 优化WebSocket心跳配置(可选)
直接禁用心跳虽然能解决连接断开问题,但更推荐调整心跳参数与后端匹配,避免RabbitMQ主动断开空闲连接:
loggingStompClient = Stomp.client(`${this.props.environment.webSocketUrl}/logging`); // 与后端RabbitMQ的心跳配置保持一致 loggingStompClient.heartbeat.outgoing = 10000; loggingStompClient.heartbeat.incoming = 10000;
验证步骤
- 修改Transport实现后,重新启动前端应用
- 触发多次日志输出(比如多次调用
logger.info('test log')) - 查看浏览器控制台的
SEND TO WEBSOCKET日志是否多次出现 - 检查后端Spring Boot的日志,确认是否接收到多条日志
按照以上步骤修复后,应该能解决Winston自定义Transport仅触发一次的问题,同时保证WebSocket稳定发送多条日志。
内容的提问来源于stack exchange,提问作者Claim
相关产品推荐
相关产品推荐

