You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sentry.captureMessage在Winston Transport的log函数中无法工作

问题:Winston自定义Sentry Transport无法捕获log方法中的消息

我尝试让Sentry与Winston配合(使用winston-transport-sentry-node),即便基础配置也无法正常运行,于是自行编写了一个简易Winston Transport类。调用Winston日志后,Sentry中能看到构造函数里的「Test message constructor」条目,但看不到log方法里的「Test message log」条目。奇怪的是,log函数中的console.log能正常打印,包括Sentry.captureMessage返回的事件ID。

相关版本:

  • winston 3.8.2
  • @sentry/node 7.37.2
  • winston-transport-sentry-node 2.7.0

自定义Transport代码:

import * as Sentry from '@sentry/node'
import * as TransportStream from 'winston-transport'

export class SentryCustomTransport extends TransportStream {
  constructor(opts) {
    super(opts)

    Sentry.init({
      dsn: process.env.SENTRY_DSN,
      environment: process.env.ENV_NAME,
      sampleRate: 1,
      tracesSampleRate: 1,
    })
    Sentry.captureMessage('Test message constructor')
  }

  log(info, callback) {
    setImmediate(() => {
      this.emit('logged', info);
    })

    console.log('Called log function')
    const eventId = Sentry.captureMessage('Test message log')
    console.log('Event ID:', eventId)

    callback()
  }
}

解决方法

核心原因

  1. Sentry初始化位置错误:将Sentry.init放在Transport构造函数中,若Winston创建多个Transport实例会重复初始化Sentry,导致内部状态异常。
  2. 异步事件未完成就终止:Sentry的事件发送是异步操作,Winston调用callback()后,进程可能提前退出,导致事件还未发送到Sentry服务器。

具体修复步骤

  1. 全局初始化Sentry
    将Sentry.init移到项目入口文件(如app.js或index.js),确保全局只初始化一次:

    // 项目入口文件
    import * as Sentry from '@sentry/node';
    
    Sentry.init({
      dsn: process.env.SENTRY_DSN,
      environment: process.env.ENV_NAME,
      sampleRate: 1,
      tracesSampleRate: 1,
      // 可选:开启调试模式排查发送问题
      debug: true
    });
    
  2. 等待Sentry事件发送完成再回调
    修改Transport的log方法,调用Sentry.flush()等待事件发送完成后再执行callback:

    log(info, callback) {
      setImmediate(() => {
        this.emit('logged', info);
      });
    
      console.log('Called log function');
      const eventId = Sentry.captureMessage('Test message log');
      console.log('Event ID:', eventId);
    
      // 等待最多2秒,确保事件发送完成
      Sentry.flush(2000)
        .then(() => callback())
        .catch(err => {
          console.error('Sentry事件发送失败:', err);
          callback(err);
        });
    }
    
  3. 避免进程提前退出
    如果是脚本类项目,需确保所有异步日志操作完成后再终止进程,比如在应用结束前手动调用Sentry.flush():

    // 应用退出前执行
    process.on('exit', () => {
      Sentry.flush(2000);
    });
    

额外排查建议

开启Sentry的debug模式后,可在控制台查看事件发送的详细日志,若存在网络或权限问题,能直接定位错误原因。


内容的提问来源于stack exchange,提问作者lookingaround

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:50:33