Node.js - logowanie / Użyj morgan i winston

102

używamy morgando rejestrowania naszej ekspresowej transformacji:

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

Ponadto używamy winstondo rejestrowania innych danych logowania:

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

Czy jest jakiś sposób na połączenie dwóch rejestratorów razem? sytuacja jest taka, że morganjest to zapis na moje standardowe wyjście, kiedy winstonzapisuje do /var/log/log-file.log.

Chciałbym, aby plik loggera łączył się z informacjami o ekspresowej transformacji i innymi informacjami, które chcę ( logger.info()) ..

Albo Smith
źródło
Jaki jest sens robienia tego, mam na myśli, dlaczego na początku potrzebowałeś morgana, dlaczego nie napisać po prostu winstona middlewrare na ekspres?
Dimitri Kopriwa

Odpowiedzi:

142

Ten artykuł świetnie radzi sobie z tym, co chcesz zrobić.

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

Do konkretnego kodu prawdopodobnie potrzebujesz czegoś takiego:

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

Spowoduje to skonfigurowanie Winstona do zapisywania dziennika w konsoli, a także pliku. Następnie możesz użyć ostatniego wyrażenia, aby przekazać dane wyjściowe z oprogramowania pośredniczącego Morgana do programu Winston.

lindsaymacvean
źródło
Czy w tym procesie możemy użyć sygnatury czasowej?
bombayquant
25
Wydaje się, że nie ma potrzeby nadpisywania logger.stream .. W moim przypadku udało mi się to zrobićapp.use(morgan("combined", { stream: { write: message => logger.info(message) }}));
Devon Sams
19
Jeśli używasz metody @ DevonSams, otrzymasz pusty wiersz między zarejestrowanymi wierszami, ponieważ zarówno morgan, jak i winston dodają podział wiersza na końcu zarejestrowanej wiadomości. Możesz po prostu odciąć wyjście z wiadomości za pomocąlogger.info(message.trim())
Timo
2
Co jeśli chcę użyć logger.error zamiast logger.info, jeśli serwer odpowie 500?
Alendorff
3
Do winston: ^3.0.0użytku winston.createLoggerzamiastnew winston.Logger
streof
21

W maszynie:

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 }));
Mahyar SEPEHR
źródło
Dlaczego małe i nie połączone?
An-droid
Nie mogłem już sprawić, żeby to działało. Wygląda na to, że typy są nieprawidłowe. stackoverflow.com/questions/50048193/…
jpetitte
7

Zaktualizuj ostatnią linię, aby usunąć ostrzeżenie

app.use(require("morgan")("combined", { stream: logger.stream }));
Jasio
źródło
3

dla Typescript innym sposobem na to, bez konieczności tworzenia klasy, jest

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

To rozwiązanie pochodzi z tej strony Github https://github.com/winstonjs/winston/issues/1385 . Należy jednak pamiętać, że istnieje niewielka różnica między naszymi kodami. Zamiast:

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

Używam:

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

Pomogło mi to, ponieważ nie jestem zbyt duży w tworzeniu zajęć.

Cris Shaki
źródło
2

Morgan ma zły zwyczaj kończenia wiadomości rozszerzeniem \n więc aby wszystko było uporządkowane, możesz zechcieć to usunąć przed napisaniem do winston.

Można to zrobić na wiele różnych sposobów, na przykład po stronie formatu w winston lub aktualizując strumień, aby nie zapisywał pliku \n

class MyStream {
    write(text: string) {
        logger.info(text.replace(/\n$/, ''));
    }
}
let myStream = new MyStream()
app.use(morgan('tiny', { stream: myStream }));
user566245
źródło