Node.js - ведение журнала / Использование morgan и winston

99

мы используем morganдля регистрации нашего экспресс-преобразования:

var morgan  = require('morgan');
morgan('combined');
// a format string
morgan(':remote-addr :method :url :uuid');
// a custom function
morgan(function (req, res) {
  return req.method + ' ' + req.url + ' ' + req.uuid;
})

Кроме того, мы используем winstonдля регистрации других наших журналов:

var winston = require('winston');
var logger = new (winston.Logger)({
  transports: [
         new (winston.transports.Console)({ level: 'info' }),
          new (winston.transports.File)({ filename: '/var/log/log-file.log' })
  ]
});

Есть ли способ объединить два регистратора вместе? теперь ситуация такова, что morganзапись на мой стандартный вывод, когда winstonзапись в /var/log/log-file.log.

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

Или Смит
источник
Какой в ​​этом смысл, я имею в виду, зачем вам понадобился морган с самого начала, почему бы просто не написать winston middlewrare для экспресса?
Дмитрий Коприва

Ответы:

141

Эта статья отлично справляется с тем, чем вы хотите заниматься.

http://tostring.it/2014/06/23/advanced-logging-with-nodejs/

Для вашего конкретного кода вам, вероятно, понадобится что-то вроде этого:

var logger = new winston.Logger({
    transports: [
        new winston.transports.File({
            level: 'info',
            filename: './logs/all-logs.log',
            handleExceptions: true,
            json: true,
            maxsize: 5242880, //5MB
            maxFiles: 5,
            colorize: false
        }),
        new winston.transports.Console({
            level: 'debug',
            handleExceptions: true,
            json: false,
            colorize: true
        })
    ],
    exitOnError: false
});

logger.stream = {
    write: function(message, encoding){
        logger.info(message);
    }
};

app.use(require("morgan")("combined", { "stream": logger.stream }));

Это настроит Winston на запись журнала в консоль, а также в файл. Затем вы можете использовать последнее выражение для передачи выходных данных промежуточного программного обеспечения morgan в winston.

Lindsaymacvean
источник
Можем ли мы использовать в этом процессе временную метку?
bombayquant
24
Не похоже, что необходимо переопределить logger.stream .. В моем случае я смог это сделатьapp.use(morgan("combined", { stream: { write: message => logger.info(message) }}));
Девон Сэмс
17
Если вы используете метод @ DevonSams, вы получите пустую строку между записанными строками, потому что и morgan, и winston добавляют разрыв строки в конец зарегистрированного сообщения. Вы можете просто вырезать перенос строки из сообщения с помощьюlogger.info(message.trim())
Timo
2
Что, если я хочу использовать logger.error вместо logger.info, если сервер отвечает 500?
Alendorff
3
Для winston: ^3.0.0использования winston.createLoggerвместоnew winston.Logger
streof
21

В машинописном тексте:

let logger = new (winston.Logger)({
    exitOnError: false,
    level: 'info',
    transports: [
        new (winston.transports.Console)(),
        new (winston.transports.File)({ filename: 'app.log'})
    ]
})

class MyStream {
    write(text: string) {
        logger.info(text)
    }
}
let myStream = new MyStream()
app.use(morgan('tiny', { stream: myStream }));
Махьяр СЕПЕР
источник
Почему крошечные и не совмещенные?
An-droid
Я больше не мог заставить это работать. Похоже, что набраны неверные. stackoverflow.com/questions/50048193/…
jpetitte
7

Обновите последнюю строку, чтобы удалить предупреждение

app.use(require("morgan")("combined", { stream: logger.stream }));
Джонни
источник
3

для Typescript другой способ сделать это без необходимости создания класса -

let logger = new (winston.Logger)({
    exitOnError: false,
    level: 'info',
    transports: [
        new (winston.transports.Console)(),
        new (winston.transports.File)({ filename: 'app.log'})
    ]
})

const myStream = {
    write: (text: string) => {
        logger.info(text)
    }
}

app.use(morgan('combined', { stream: myStream }));

Это решение было взято с этой страницы Github https://github.com/winstonjs/winston/issues/1385 . Однако важно отметить, что между нашими кодами есть небольшая разница. Вместо того:

app.use(morgan('combined', { myStream }));

Я использую:

app.use(morgan('combined', { stream: myStream }));

Это помогло мне, так как я не слишком разбираюсь в создании классов.

Крис Шаки
источник
2

У Моргана есть дурная привычка заканчивать сообщение символом, \nпоэтому, чтобы все было упорядочено, вы можете удалить его, прежде чем писать его Уинстону.

Это можно сделать разными способами, например, на стороне формата в Winston или обновив поток, чтобы не писать \n

class MyStream {
    write(text: string) {
        logger.info(text.replace(/\n$/, ''));
    }
}
let myStream = new MyStream()
app.use(morgan('tiny', { stream: myStream }));
user566245
источник