Node.js: Winston: могу ли я добавить метаданные по умолчанию ко всем сообщениям журнала

Я использую Winston в Node.js для регистрации. Я знаю, что могу добавлять метаданные индивидуально к каждому сообщению журнала, но есть ли способ указать набор метаданных по умолчанию, который будет добавляться к каждому сообщению журнала (например, имя приложения), поскольку я не хочу указывать его каждый раз Мне нужно отправить сообщение в журнал.

8 ответов

Решение

Нет встроенного способа сделать это, но вы можете добавить его самостоятельно - вот как:

Во-первых, настройте регистратор, как обычно. Например:

var logger = new (winston.Logger)({
            "exitOnError" : true,
            "transports" : [
                new (winston.transports.Console)({ "colorize" : true, "level" : "silly", "silent" : false, "handleExceptions" : false }),
            ]
        });

Затем переопределите метод log() (он всегда вызывается методами уровня - logger.foo() на самом деле звонки logger.log('foo').)

logger.log = function(){
  var args = arguments;
  if(args[2]) args[3] = args[2];
  args[2] = {
    "foo" : "bar"
  }
  winston.Logger.prototype.log.apply(this,args);
}

Все, что я делаю выше, это делаю так, когда logger.log() вызывается, вместо этого вызывается вышеуказанный метод, который добавляет метаданные (в данном случае объект, содержащий foo ключ). Затем он вызывает метод Winston Logger.log из соответствующего контекста.

Приведенный выше код будет в модуле, который вы создаете, в нижней части просто экспортируйте регистратор:

module.exports = logger;

и импортируйте модуль логгера вместо модуля winston в ваши подклассы.

var logger = require('./logger.js');

Надеюсь, это поможет!

Для Winston v2 (см. Комментарии)

Есть сейчас rewriters это документированный и официальный способ сделать это:

logger.rewriters.push(function(level, msg, meta) {
  meta.app = 'myApp';

  return meta;
});

Добавит недвижимость app для каждого метаданных, проходящих через этот регистратор.
Вы также можете объявить это при сборке регистратора:

new (winston.Logger)({
        level: config.log[file].level,
        rewriters: [
            (level, msg, meta) => {
                meta.app = 'myApp';
                return meta;
            }
        ],
        transports: [
            /*your transports*/
        ]
});

Для Winston v3:

const addAppNameFormat = winston.format(info => {
  info.appName = "My Program";
  return info;
});

const logger = winston.createLogger({
  format: winston.format.combine(
    addAppNameFormat(),
    winston.format.json()
  ),
transports: [new winston.transports.Console()]
});

logger.warn('Danger Will Robinson!');
// {"message":"Danger Will Robinson!","level":"warn","appName":"My Program"}

См.: https://github.com/winstonjs/winston/blob/HEAD/UPGRADE-3.0.md#migrating-filters-and-rewriters-to-formats-in-winston3

Есть сейчас (20.08.19) недвижимость defaultMeta это передается createLogger который будет вводить указанную вами мета в каждый журнал.

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  defaultMeta: { service: 'user-service' },
  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' })
  ]
});

Я искал способ добавить идентификатор доставки github во все мои журналы.

Я использую Winston 3 и defaultMeta добытчики вместе с express-http-context

      // logger.js 
const logger = (filename) => winston.createLogger({
    ...
    defaultMeta: {
        get deliveryId () { return httpContext.get('deliveryId'); },
        get deliveryEvent () { return httpContext.get('deliveryEvent'); },
        module: filename,
    },
    ...
});

module.exports = (fileName) => {
    return logger(fileName);
}

в других моих модулях:

      // foo.js
const logger = require('./logger')(__filename)

module.exports = async(someInput) => {
    logger.debug('hello ' + someInput)
}

https://github.com/winstonjs/winston/issues/1626#issuecomment-531142958

Другой вариант с выводом, более похожим на log4j(s):

Существует (в настоящее время недокументированное) свойство label в транспорте консоли, которое добавит метку к выводу (json или строка):

var _ = require('lodash');
var winston = require('winston');
var path = require('path');
var baseDir = path.resolve(__dirname, '..');

// SETUP WINSTON LOGGER
var container = new winston.Container();
container.add("exception", {
    console: {
        handleExceptions: true,
        timestamp: true,
        label: "EXCEPTION",
        colorize: true
    }
});
container.get("exception").exitOnError = false;
var keys = [];

module.exports = function(filename) {
    var label = path.relative(baseDir, filename);
    if (!_.contains(keys, label)) {
        container.add(label, {
            console: {
                handleExceptions: false,
                level: 'debug',
                timestamp: true,
                label: label,
                colorize: true
            }
        });
        keys.push(label);
    }
    var logger = container.get(label);
    logger.exitOnError = false;
    return logger;
};

А в других модулях это нужно так:

var logger = require('./logger')(__filename);

Пример вывода:

2014-07-23T07:05:27.770Z - info: [config/config.js] .......

Я нашел лучший способ, используя утилиту-расширение, основываясь на том, что я прочитал в этом блоге. Он будет добавлять данные во всех случаях, которые я нашел полезными для перехвата logger.info против logger.log("информация", сообщение), и не будет перезаписывать другие ваши аргументы.

logger.log = function(){
   var args = arguments;
   var level = args[0];

   var newArgs = {
        foo: "bar",
        baz: "abc"
   };
   var originalMeta = args[2] || {};
   args[2] = extend(originalMeta, newArgs);

   winston.Logger.prototype.log.apply(this,args);
};

Будет выводить в консоли и в ваших логах.

Я используюwinston@3x, есть 2 уровняmetadata,defaultиchild

      // logger.ts

const logger = createLogger({
  level:"info",
  defaultMeta: { app: "MyApp" },
  handleExceptions: true,
  format: format.combine(
    format.errors({ stack: true }),
    format.timestamp(),
    format.json()
  ),
  transports: [new transports.Console()],
});


export default function getLogger(childName = ""): Logger {
  if (!childName) {
    return logger;
  }
  return logger.child({ childName });
}

      
// some-where.ts

const logger = getLogger("OnEarth")
logger.info("dog - bark bark")

-------- выход ------------

      {
  ....
  level: "info",
  message: "dog - bark bark",
  app: "MyApp",
  childName: "OnEarth"
}
Другие вопросы по тегам