10

我试图使用winston进行日志记录,但我看到如果我想用2个arg获取数据,那么我会得到日志,但如果我想得到3个参数,那么我就没有得到数据,

前任:

logger = new (winston.Logger)({
transports: [
   new (winston.transports.Console)({colorize : true, timestamp:true}),
 ]
});

现在尝试获取如下日志:

 1. logger.info("We got the data %s, %d", data, port);
 O/P: We got the data %s, %d  => No data and port value
 2. logger.info("We got the data, port", data, port);
 O/P: We got the data, port   => No data and port value
 3. logger.info("We got the data", data);
 ===> Getting the data correctly.

您能否让我知道我在 1、2 中遗漏了什么,或者winston 真的没有在 1 和 2 的情况下记录数据吗?

4

5 回答 5

8

这对我和winston 3.2.x 有效:

const { format, createLogger, transports } = require('winston');
const jsonStringify = require('fast-safe-stringify');

const logLikeFormat = {
  transform(info) {
    const { timestamp, label, message } = info;
    const level = info[Symbol.for('level')];
    const args = info[Symbol.for('splat')];
    const strArgs = args.map(jsonStringify).join(' ');
    info[Symbol.for('message')] = `${timestamp} [${label}] ${level}: ${message} ${strArgs}`;
    return info;
  }
};

const debugFormat = {
  transform(info) {
    console.log(info);
    return info;
  }
};

const logger = createLogger({
  format: format.combine(
    // debugFormat, // uncomment to see the internal log structure
    format.timestamp(),
    format.label({ label: 'myLabel' }),
    logLikeFormat,
    // debugFormat, // uncomment to see the internal log structure
  ),
  transports: [
    new transports.Console()
  ]
});


logger.info('foo', 'bar', 1, [2, 3], true, { name: 'John' });

这导致:2019-07-04T21:30:08.455Z [myLabel] info: foo "bar" 1 [2,3] true {"name":"John"}

基本上format.combineinfo对象设置管道。对于每个格式函数,transform都会调用并写入最终的日志消息以info[Symbol.for('message')] 希望这会有所帮助

于 2019-07-04T21:33:15.773 回答
6

由于 Winston API 不像 那样工作console.log,因此一种解决方法是创建一个包装函数,它util.format以下列方式使用:

const util = require('util')   

...

function log(...msg) {
  logger.info(util.format(...msg))
}

然后你可以像这样调用日志: log('my log entry', 'foo, 'bar')

这将像这样记录:{"message":"my log entry foo bar","level":"info"}

于 2018-10-01T14:37:25.817 回答
3

You are assuming there is a varargs style API, but there is not. The full API is level, msg, meta, callback, but when you use one of the methods that is the level, then it's just msg, meta, callback. You need to construct a single meta object and pass that.

https://github.com/flatiron/winston/blob/master/lib/winston/logger.js#L115

//
// ### function log (level, msg, [meta], callback)
// #### @level {string} Level at which to log the message.
// #### @msg {string} Message to log
// #### @meta {Object} **Optional** Additional metadata to attach
// #### @callback {function} Continuation to respond to when complete.
// Core logging method exposed to Winston. Metadata is optional.
//

https://github.com/flatiron/winston#logging-with-metadata

于 2013-02-12T16:59:09.483 回答
2

我通过包装 winston 函数并使用包装器来解决这个问题。我希望现在有更好的解决方案。

var logger = new (winston.Logger)({
        transports:[new (winston.transports.Console)({ json : false, timestamp : true, level : 0, colorize : true}),
                    new (winston.transports.File)({ filename: filepath, json : false, timestamp : true, level : 0, colorize: true })]
    });

// pass in function arguments object and returns string with whitespaces
function argumentsToString(v){
    // convert arguments object to real array
    var args = Array.prototype.slice.call(v);
    for(var k in args){
        if (typeof args[k] === "object"){
            // args[k] = JSON.stringify(args[k]);
            args[k] = util.inspect(args[k], false, null, true);
        }
    }
    var str = args.join(" ");
    return str;
}


    // wrapping the winston function to allow for multiple arguments
    var wrap = {};
    wrap.info = function () {
        logger.log.apply(logger, ["info", argumentsToString(arguments)]);
    };

    wrap.error = function () {
        logger.log.apply(logger, ["error", argumentsToString(arguments)]);
    };

    wrap.warn = function () {
        logger.log.apply(logger, ["warn", argumentsToString(arguments)]);
    };

    wrap.debug = function () {
        logger.log.apply(logger, ["debug", argumentsToString(arguments)]);
    };

/// 然后按原样返回 wrap 是您的记录器。/// 并使用类似 log.info(1,2,3,4,"foo","bar");

于 2013-03-21T12:09:19.003 回答
0

这是我的日志记录模块,它适用于我的所有项目。

const winston = require('winston');

module.exports = function() {
    const logger = winston.createLogger({
        format: winston.format.combine(
            winston.format.timestamp(),
            winston.format.colorize(),
            winston.format.json()           
        ),
        transports: [
          new winston.transports.File({ filename: 'error.log' }),
        ]
      });

      if (process.env.NODE_ENV !== 'production') {
        logger.add(new winston.transports.Console({
            format: winston.format.combine(
                winston.format.timestamp(),
                winston.format.colorize(),
                winston.format.json()               
            )
        }));
      }

    process.on('unhandledRejection', (error) =>{
        logger.error(error.stack);
    });

    process.on('uncaughtException', (error) =>{
        logger.error(error.stack);
    }); 
}
于 2020-01-20T10:41:19.503 回答