【问题标题】:Winston not displaying error detailsWinston 不显示错误详细信息
【发布时间】:2019-01-08 21:12:57
【问题描述】:

我正在使用winston 进行日志记录,并且大多数情况下它运行良好,但是当出现异常时,它只是不打印任何详细信息。

这是我配置winston的代码:

// Create logger
const logger = winston.createLogger()

// Create timestamp format
const tsFormat = () => (new Date()).toLocaleTimeString()

// Attach transports based on app mode
if (process.env.APP_MODE === 'production') {
  // Log to file
  logger.add(new (winston.transports.DailyRotateFile)({
    filename: path.join(__dirname, '../logs/errors-%DATE%.log'),
    datePattern: 'YYYY-MM-DD-HH',
    zippedArchive: true,
    format: winston.format.json(),
    handleExceptions: true
  }))
} else {
  // Log to the console
  logger.add(new (winston.transports.Console)({
    timestamp: tsFormat,
    colorize: true,
    handleExceptions: true
  }))
}

module.exports = logger

我也在使用Express,在我的错误处理中间件中,我有这个代码:

const logger = require('../config/winston')
function (err, req, res, next) {
    console.log(err)
    logger.error(err)
    res.status(500).send({ error: 'Please try again later.' })
}

问题是当出现错误时所有winston的日志都是:

{"级别":"错误"}

虽然旧的 console.log() 显示:

TypeError: Cannot read property 'filename' of undefined
    at router.post (/Users/balazsvincze/Desktop/testapi/app/routes/upload.js:16:33)
    at Layer.handle [as handle_request] (/Users/de/Desktop/testapi/node_modules/express/lib/router/layer.js:95:5)
    at next (/Users/balazsvincze/Desktop/testapi/node_modules/express/lib/router/route.js:137:13)
    at Immediate.<anonymous> (/Users/balazsvincze/Desktop/testapi/node_modules/multer/lib/make-middleware.js:53:37)
    at runCallback (timers.js:814:20)
    at tryOnImmediate (timers.js:768:5)
    at processImmediate [as _immediateCallback] (timers.js:745:5)

如何让winston 记录类似的内容,包括堆栈跟踪?

非常感谢!

编辑:如果我将 logger.error(err) 行更改为 logger.error(err.message),至少我得到这个:

{"message":"无法读取属性‘文件名’的 未定义","级别":"错误"}

离我所追求的还很远。

【问题讨论】:

  • 我不敢相信这个问题不是更受欢迎。这是设置 SERN 应用程序时我需要做的第一件事

标签: node.js express logging winston


【解决方案1】:

一种快速而肮脏的方法是记录err.stack:

logger.error(err.stack);

更复杂的方法是专门为Error 实例实现custom format。在this Github issue 中有一些关于如何实现它的示例代码。

【讨论】:

    【解决方案2】:

    使用格式。

    const { combine, timestamp, label, printf } = winston.format;
    const myFormat = printf(info => {
        if(info instanceof Error) {
            return `${info.timestamp} [${info.label}] ${info.level}: ${info.message} ${info.stack}`;
        }
        return `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`;
    });
    winston.createLogger({
        level: "info",
        format: combine(
            winston.format.splat(),
            label({ label: filename}),
            timestamp(),
            myFormat,
        ),
        transports: [
        //
        // - Write to all logs with level `info` and below to `combined.log`
        // - Write all logs error (and below) to `error.log`.
        //
            new winston.transports.File({ filename: path.join(os.tmpdir(), "test", "test.log"), level: "info" }),
        ],
    });
    

    【讨论】:

      【解决方案3】:

      我认为你缺少的是winston.createLogger 中的format.errors({ stack: true })。

      const logger = winston.createLogger({
        level: 'debug',
        format: format.combine(
          format.errors({ stack: true }),
          print,
        ),
        transports: [new transports.Console()],
      });
      

      更多信息请参见this GitHub thread。

      发生这种情况的原因是有趣的Error 对象属性,如.stack,是不可枚举的。一些函数检查其参数是否为Error 实例,如console.error,而其他函数忽略所有不可枚举的属性,如winston.&lt;log-level&gt; 和JSON.stringify。

      > console.error(new Error('foo'))
      Error: foo
          at repl:1:15
          at Script.runInThisContext (vm.js:124:20)
          ...(abbr)
      
      > JSON.stringify(new Error('foo'))
      '{}'
      

      话虽如此,让错误记录器基本上忽略错误是非常糟糕的可用性......我只是为此浪费了太多时间。

      【讨论】:

      • 我们使用像 Winston 这样的记录器的主要原因是什么?尽可能详细地查看错误。很遗憾,默认情况下它不能像console.log 那样打印错误对象的完整详细信息。
      • 如果您使用winston.format.combine(),请确保将format.errors({ stack: true })放在格式之上
      【解决方案4】:

      我之前遇到过同样的问题,我知道这有点问题,但对于仍在寻找解决方案的人来说,可以使用utils-deep-clone 包。只是在 Winston 上方添加了一个层来处理错误对象。

      const winston = require('winston')
      const { toJSON } = require('utils-deep-clone')
      
      const winstonLogger = new (winston.Logger)({
        transports: [
          new (winston.transports.Console)()
        ]
      })
      
      const log = (message, payload) => {
        try {
          payload = toJSON(payload)
          return winstonLogger.log('info', message, payload)
        } catch(error) {
          console.error('some error occured while consoling')
        }
      }
      
      const testObj = {
        error: new Error('It should work')
      }
      
      log('Testing few bugs', testObj)
      

      输出将是:

      info: Testing few bugs message=It should work, stack=Error: It should work
          at Object.<anonymous> (/Users/atishay/Desktop/utils-error-deep-log/logger.js:20:10)
          at Module._compile (module.js:652:30)
          at Object.Module._extensions..js (module.js:663:10)
          at Module.load (module.js:565:32)
          at tryModuleLoad (module.js:505:12)
          at Function.Module._load (module.js:497:3)
          at Function.Module.runMain (module.js:693:10)
          at startup (bootstrap_node.js:188:16)
          at bootstrap_node.js:609:3
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-05
        • 1970-01-01
        • 2012-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多