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()).


Який сенс робити це, я маю на увазі, навіщо тобі спочатку був Morgan, чому б просто не написати Winston Middlewrare для Express?
Димитрій Копріва,

Відповіді:


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 }));

Це налаштує Вінстона на запис журналу на консоль, а також файлу. Тоді ви можете використовувати останній вираз, щоб передати вихідні дані з проміжного програмного забезпечення morgan у winston.


Чи можемо ми використовувати позначку часу в цьому процесі?
bombayquant

23
Здається, не потрібно перевизначати logger.stream .. У моєму випадку я зміг це зробитиapp.use(morgan("combined", { stream: { write: message => logger.info(message) }}));
Девон Семс

17
Якщо ви використовуєте метод @ DevonSams, ви отримаєте порожній рядок між зареєстрованими рядками, тому що і morgan, і winston додають розрив рядка в кінці повідомлення, що реєструється. Ви можете просто обрізати рядок з повідомлення за допомогоюlogger.info(message.trim())
Тимо

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 }));

Чому крихітні, а не поєднані?
Ан-дроїд

Я більше не міг змусити це працювати. Здається, набори неправильні. 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 }));

Це допомогло мені, оскільки я не надто великий у створенні класів.


1

Морган має погану звичку закінчувати повідомлення \nтак, щоб зробити все впорядкованим, можливо, ви захочете видалити це, перш ніж писати його Вінстону.

Це можна зробити різними способами, наприклад, на стороні форматування в Вінстоні, або оновивши потік, щоб не писати файл \n

class MyStream {
    write(text: string) {
        logger.info(text.replace(/\n$/, ''));
    }
}
let myStream = new MyStream()
app.use(morgan('tiny', { stream: myStream }));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.