【问题标题】:How to Log Full Stack Trace with Winston 3?如何使用 Winston 3 记录完整的堆栈跟踪?
【发布时间】:2018-04-24 04:59:21
【问题描述】:

我的记录器设置如下:

const myFormat = printf(info => {
   return `${info.timestamp}: ${info.level}: ${info.message}: ${info.err}`;
 });


 const logger =
   winston.createLogger({
   level: "info",
   format: combine(timestamp(), myFormat),

   transports: [
     new winston.transports.File({
     filename:
      "./logger/error.log",
        level: "error"
    }),
     new winston.transports.File({
       filename:
       "./logger/info.log",
       level: "info"
   })
  ]
})

然后我正在注销一些这样的错误:

logger.error(`GET on /history`, { err });

如何通过错误传输记录错误的完整堆栈跟踪?我尝试传入 err.stack,结果显示为未定义。

谢谢!

【问题讨论】:

    标签: javascript node.js logging winston


    【解决方案1】:

    您可以编写一个格式化程序将error.stack 传递给日志。

    const errorStackFormat = winston.format(info => {
      if (info instanceof Error) {
        return Object.assign({}, info, {
          stack: info.stack,
          message: info.message
        })
      }
      return info
    })
    
    const logger = winston.createLogger({
      transports: [ ... ],
      format: winston.format.combine(errorStackFormat(), myFormat)
    })
    
    logger.info(new Error('yo')) // => {message: 'yo', stack: "Error blut at xxx.js:xx ......"} 
    

    (输出将取决于您的配置)

    【讨论】:

    • 什么是myFormat
    • 如果我们需要记录一条消息,然后是一个错误(类似于 Java 的 log4j 等):logger.error('Failed to do sth', e)
    【解决方案2】:

    2021 年 1 月 14 日更新 - 这不再适用于新版本的 Winston。

    原答案

    @Ming 的回答让我部分明白了,但是要对错误进行字符串描述,这就是我在我们的问题上进行完整堆栈跟踪的方式:

    import winston from "winston";
    
    const errorStackTracerFormat = winston.format(info => {
        if (info.meta && info.meta instanceof Error) {
            info.message = `${info.message} ${info.meta.stack}`;
        }
        return info;
    });
    
    const logger = winston.createLogger({
        format: winston.format.combine(
            winston.format.splat(), // Necessary to produce the 'meta' property
            errorStackTracerFormat(),
            winston.format.simple()
        )
    });
    
    logger.error("Does this work?", new Error("Yup!"));
    
    // The log output:
    //   error: Does this work? Error: Yup!
    //       at Object.<anonymous> (/path/to/file.ts:18:33)
    //       at ...
    //       at ...
    

    【讨论】:

    • 我注意到这是可行的,但是文档在哪里说需要将错误对象放在第二个参数中?
    • @5413668060 您不应该将错误对象放在第二个参数中。那是给meta data的。如果您将错误对象作为第一个参数传递,那么您必须将errorStackTracerFormat 函数中的info.meta.XXX 引用更改为info.XXX
    • 抱歉,您的示例并没有做到它声称的那样。
    • 是的,info 对象的 console.dir 不显示任何元数据。相反,它显示了一些 splat 符号。内部肯定发生了变化。
    【解决方案3】:

    这是我的logger.jswinston": "^3.1.0

    const { createLogger, format, transports } = require('winston');
    const { combine, timestamp, printf, colorize, splat } = format;
    
    const myFormat = printf((info) => {
      if (info.meta && info.meta instanceof Error) {
        return `${info.timestamp} ${info.level} ${info.message} : ${info.meta.stack}`;
      }
      return `${info.timestamp} ${info.level}: ${info.message}`;
    });
    
    const LOG_LEVEL = process.env.LOG_LEVEL || 'debug';
    const logger = createLogger({
      transports: [
        new (transports.Console)(
          {
            level: LOG_LEVEL,
            format: combine(
              colorize(),
              timestamp(),
              splat(),
              myFormat
            )
          }
        )
      ]
    });
    module.exports = logger;
    

    【讨论】:

      【解决方案4】:

      对于winston 版本3.2.0+,以下将添加堆栈跟踪到日志输出:

      import { createLogger, format, transports } from 'winston';
      
      const { combine, timestamp, prettyPrint, colorize, errors,  } = format;
      
      
      const logger = createLogger({
        format: combine(
          errors({ stack: true }), // <-- use errors format
          colorize(),
          timestamp(),
          prettyPrint()
        ),
        transports: [new transports.Console()],
      });  
      

      参考:https://github.com/winstonjs/winston/issues/1338#issuecomment-482784056

      【讨论】:

        【解决方案5】:

        这是我的记录器配置。添加了errors({ stack: true }),感谢Murli Prajapati ans 和printf 函数中的小技巧。我的温斯顿版本是3.2.1

        const {format, transports} = require('winston');
        const { timestamp, colorize, printf, errors } = format;
        const { Console, File } = transports;
        LoggerConfig = {
                level: process.env.LOGGER_LEVEL || 'debug',
                transports: [
                    new Console(),
                    new File({filename: 'application.log'})
                ],
                format: format.combine(
                    errors({ stack: true }),
                    timestamp(),
                    colorize(),
                    printf(({ level, message, timestamp, stack }) => {
                        if (stack) {
                            // print log trace 
                            return `${timestamp} ${level}: ${message} - ${stack}`;
                        }
                        return `${timestamp} ${level}: ${message}`;
                    }),
                ),
                expressFormat: true, // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
                colorize: false, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
                ignoreRoute: function (req, res) {
                    return false;
                } // optional: allows to skip some log messages based on request and/or response
        }
        

        我在 express-winston 和一般日志中使用相同的配置。

        const winston = require('winston');
        const expressWinston = require('express-winston');
        
        /**
         * winston.Logger
         * logger for specified log message like console.log
         */
        global.__logger = winston.createLogger(LoggerConfig);
        /**
         * logger for every HTTP request comes to app
         */
        app.use(expressWinston.logger(LoggerConfig));
        
        

        【讨论】:

          【解决方案6】:

          这是 Winston 3.2 的另一个版本。

          现在 Winston 带有一个内置的堆栈跟踪格式化程序,但如果相同的格式化程序有 winston.format.simple() 组合,它似乎不会触发。因此,您需要使用 winston.format.printf 来代替 Kirai Mali 的回答。我不知道如何在同一配置中同时配置 winston.format.errors()winston.format.simple()

          基于当前 Winston README 示例和上面的答案,这是我使用 JSON 格式日志文件的配置,但对于本地开发控制台,它仍然提供彩色日志行和良好的堆栈跟踪。

          
          // Use JSON logging for log files
          // Here winston.format.errors() just seem to work
          // because there is no winston.format.simple()
          const jsonLogFileFormat = winston.format.combine(
            winston.format.errors({ stack: true }),
            winston.format.timestamp(),
            winston.format.prettyPrint(),
          );
          
          // Create file loggers
          const logger = winston.createLogger({
            level: 'debug',
            format: jsonLogFileFormat,
            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: 'error.log', level: 'error' }),
              new winston.transports.File({ filename: 'combined.log' })
            ],
            expressFormat: true,
          });
          
          // When running locally, write everything to the console
          // with proper stacktraces enabled
          if (process.env.NODE_ENV !== 'production') {
            logger.add(new winston.transports.Console({
              format:  winston.format.combine(
                          winston.format.errors({ stack: true }),
                          winston.format.colorize(),
                          winston.format.printf(({ level, message, timestamp, stack }) => {
                            if (stack) {
                                // print log trace
                                return `${timestamp} ${level}: ${message} - ${stack}`;
                            }
                            return `${timestamp} ${level}: ${message}`;
                        }),
                      )
            }));
          }
          

          【讨论】:

          猜你喜欢
          • 2013-11-16
          • 2014-01-06
          • 1970-01-01
          • 2021-02-07
          • 1970-01-01
          • 2011-04-06
          • 1970-01-01
          • 1970-01-01
          • 2011-03-29
          相关资源
          最近更新 更多