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


94

Я хочу добавить в журналы метку времени. Как лучше всего этого добиться?


Это остается слишком широким, потому что вы НЕ МОЖЕТЕ сделать это с клиентской машины.
Джошуа

Ответы:


113

Я сам имел дело с той же проблемой. Я смог это сделать двумя способами.

Когда вы включаете Winston, он обычно по умолчанию добавляет транспорт консоли. Чтобы метки времени работали в этом случае по умолчанию, мне нужно было либо:

  1. Удалите консольный транспорт и снова добавьте с опцией отметки времени.
  2. Создайте свой собственный объект Logger с параметром timestamp, установленным в значение true.

Первое:

var winston = require('winston');
winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {'timestamp':true});

Второй, более чистый вариант:

var winston = require('winston');
var logger = new (winston.Logger)({
    transports: [
      new (winston.transports.Console)({'timestamp':true})
    ]
});

Некоторые другие варианты консольного транспорта можно найти здесь :

  • level: Уровень сообщений, которые этот транспорт должен регистрировать (по умолчанию «отладка»).
  • silent: логический флаг, указывающий, следует ли подавлять вывод (по умолчанию false).
  • colorize: логический флаг, указывающий, следует ли раскрашивать вывод (по умолчанию false).
  • timestamp: логический флаг, указывающий, следует ли добавлять к выводу временные метки (по умолчанию false). Если функция указана, ее возвращаемое значение будет использоваться вместо меток времени.

1
Удивительно и просто одновременно. Спасибо!
kolrie

7
Это круто. Я обычно помещаю это в специальный файл, чтобы я мог легко получить свой настроенный регистратор из любого файла, т.е. я помещаю приведенный выше код (вариант 2) в новый файл logger.js, за которым следует module.exports = logger; затем из любого файла я делаю var logger = require ('./ logger.js'), а затем могу выполнить logger.info ('hello') из любого файла и получить ту же конфигурацию Winston.
JHH

TypeError: (промежуточное значение) не является функцией
Urasquirrel

84

Выше ответы не помогли мне. Если вы пытаетесь добавить метку времени в свои журналы, используя последнюю версию Winston - 3.0.0-rc1, это сработало как шарм:

    const {transports, createLogger, format} = require('winston');

    const logger = createLogger({
        format: format.combine(
            format.timestamp(),
            format.json()
        ),
        transports: [
            new transports.Console(),
            new transports.File({filename: 'logs/error/error.log', level: 'error'}),
            new transports.File({filename: 'logs/activity/activity.log', level:'info'})
        ]
    });

Я использовал format.combine (). Поскольку мне нужна была метка времени для всех моих транспортов, я добавил параметр форматирования в createLogger, а не внутри каждого транспорта. Мои результаты на консоли и в файле (activity.log) выглядят следующим образом:

{"message":"Connected to mongodb","level":"info","timestamp":"2018-02-01T22:35:27.758Z"}
{"message":"Connected to mongodb","level":"info","timestamp":"2018-02-01T22:35:27.758Z"}

Мы можем добавить форматирование к этой отметке времени в 'format.combine ()', как обычно, используя:

format.timestamp({format:'MM-YY-DD'})

16

Мы тоже можем это сделать

var winston = require('winston');
const { createLogger, format, transports } = require('winston');
var config = require('../configurations/envconfig.js');

var loggerLevel = process.env.LOGGERLEVEL ||  config.get('LOGGERLEVEL');

var logger = winston.createLogger({
  format: format.combine(
    format.timestamp({
      format: 'YYYY-MM-DD HH:mm:ss'
    }),
    format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`+(info.splat!==undefined?`${info.splat}`:" "))
  ),
  transports: [
    new (winston.transports.Console)({ level: loggerLevel }),
  ]
});
module.exports = logger;

Это тоже работает logger.info('Message', someObject)? Я устанавливаю собственный формат с помощью комбайна, и мне кажется, что я не могу someObjectвключить его в сообщение журнала.
Something

1
Я смог быть someObjectвключенным с помощью следующего оператора printf ${info.timestamp} [${info.level.toUpperCase()}]: ${info.message} ${JSON.stringify(info)}. Он включает в себя уровень, временную метку и сообщение, которое, я думаю, я могу удалить.
Something

9

Вы можете использовать встроенную утилиту и forever для ведения журнала с отметкой времени для вашего сервера nodejs. Когда вы запускаете сервер, добавьте вывод журнала как часть параметра:

forever start -ao log/out.log server.js

А затем вы можете написать util в своем server.js

server.js

var util = require('util');
util.log("something with timestamp");

В файле out.log результат будет выглядеть примерно так:

out.log

15 Mar 15:09:28 - something with timestamp

1
К сожалению, util.error()пропускает временную метку вывода.
Саран

4

Хотя я не знаю Winston, это предложение. Я использую log4js для ведения журнала, и мои журналы по умолчанию выглядят так

[2012-04-23 16:36:02.965] [INFO] Development - Node Application is running on port 8090
[2012-04-23 16:36:02.966] [FATAL] Development - Connection Terminated to  '127.0.0.1' '6379'

Разработка - это среда моего процесса узла, а [INFO | FATAL] - уровень журнала

В log4js возможно ведение различных профилей для ведения журнала. У меня есть профили разработки и производства. Также существуют типы регистраторов, такие как приложение для смены файлов, приложение для консоли и т. Д. В качестве дополнения ваши файлы журнала будут красочными в зависимости от уровня журнала [Trace, Info, Debug, Error, Fatal];)

log4js переопределит ваш console.log. Теперь это настраиваемый параметр в версии 0.5+.


К вашему сведению: более новые версии log4js-node (0.5+) не переопределяют console.log автоматически.
Jeff Hiltz

@jeffhiltz Вы правы :) Теперь это настраиваемый параметр
Tamil


2

Иногда формат метки времени по умолчанию может быть вам неудобен. Вы можете переопределить его своей реализацией.

Вместо того

var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
  new (winston.transports.Console)({'timestamp':true})
]
});

ты можешь написать

var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
  new (winston.transports.Console)({
     'timestamp': function() {
        return <write your custom formatted date here>;
     }
  })
]
});

См. Https://github.com/winstonjs/winston#custom-log-format для подробностей.


1

Другое решение - поместить регистратор в файл, который экспортирует некоторые функции, такие как logger.info (), logger.error () и т. Д., Тогда вы просто передаете дополнительный ключ, который будет отправляться в каждом журнале сообщений.

loggerService.js

const logger = winston.createLogger({ ... })

function handleLog(message, level) {
  const logData = {
    timestamp: Date.now(),
    message,
  }

  return logger[level](logData)
}

function info(message) {
  handleLog(message, 'info')
}

function error(message) {
  handleLog(message, 'error')
}

function warn(message) {
  handleLog(message, 'warn')
}

module.exports = {
  info,
  error,
  warn
}

любой-файл.js

const logger = require('./services/loggerService')

logger.info('Hello World!')

ваш-log.log

{"timestamp":"2019-08-21 06:42:27","message":"Hello World!","level":"info"}

1

Я взял ответ Бисвадева и создал строковый объект JSON. Таким образом, если мне нужно будет обработать журналы позже, они будут в хорошо структурированном формате.

const winston = require('winston');
const { createLogger, format, transports } = require('winston');

const dotenv = require('dotenv');
dotenv.config();

var logger = createLogger({
    level: 'info',
    format: format.combine(
        format.timestamp({
            format: 'YYYY-MM-DD HH:mm:ss',
        }),
        format.printf((info) =>
            JSON.stringify({
                t: info.timestamp,
                l: info.level,
                m: info.message,
                s: info.splat !== undefined ? `${info.splat}` : '',
            }) + ','
        )
    ),
});

if (process.env.NODE_ENV !== 'PRODUCTION') {
    logger.add(new transports.Console({ format: winston.format.cli() }));

    // Turn these on to create logs as if it were production
    // logger.add(new transports.File({ filename: 'log/output/error.log', level: 'error' }));
    // logger.add(new transports.File({ filename: 'log/output/warn.log', level: 'warn' }));
    // logger.add(new transports.File({ filename: 'log/output/info.log', level: 'info' }));
} else {
    logger.add(new transports.File({ filename: 'log/output/error.log', level: 'error' }));
    logger.add(new transports.File({ filename: 'log/output/warn.log', level: 'warn' }));
    logger.add(new transports.File({ filename: 'log/output/info.log', level: 'info' }));
}

module.exports = {
    logger,
};

Применение:

app.listen(port, () => logger.info(`app is running on port ${port}`));

Выход:

файл info.log:

{"t":"2020-08-06 08:02:05","l":"info","m":"app is running on port 3001","s":""},

Приставка:

info:    app is running on port 3001
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.