Jak mogę dodać znacznik czasu do dzienników za pomocą biblioteki Node.js Winston?


94

Chcę dodać sygnaturę czasową do dzienników. Jaki jest najlepszy sposób, aby to osiągnąć?


To pozostaje zbyt szerokie, ponieważ NIE możesz tego zrobić z komputera klienta.
Joshua

Odpowiedzi:


113

Sam miałem do czynienia z tym samym problemem. Mogłem to zrobić na dwa sposoby.

Gdy dołączasz Winston, zwykle domyślnie dodaje się transport konsoli. Aby sygnatury czasowe działały w tym domyślnym przypadku, musiałem:

  1. Usuń transport konsoli i dodaj ponownie z opcją znacznika czasu.
  2. Utwórz własny obiekt Logger z opcją timestamp ustawioną na true.

Pierwszy:

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

Druga i czystsza opcja:

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

Niektóre z innych opcji transportu konsoli można znaleźć tutaj :

  • poziom: poziom komunikatów, które ten transport powinien rejestrować (domyślnie „debugowanie”).
  • silent: flaga logiczna wskazująca, czy wstrzymać wyjście (domyślnie false).
  • colorize: flaga logiczna wskazująca, czy powinniśmy pokolorować wyjście (domyślnie false).
  • timestamp: flaga logiczna wskazująca, czy powinniśmy poprzedzić wyjście znacznikami czasu (domyślnie false). Jeśli określono funkcję, zamiast znaczników czasu zostanie użyta jej wartość zwracana.

1
Niesamowite i jednocześnie proste. Dziękuję Ci!
kolrie

7
To jest świetne. Zwykle pakuję to w dedykowany plik, aby móc łatwo pobrać skonfigurowany rejestrator z dowolnego pliku, tj. Umieściłem powyższy kod (opcja 2) w nowym pliku logger.js, a następnie module.exports = logger; następnie z dowolnego pliku robię var logger = require ('./ logger.js'), a następnie mogę zrobić logger.info ('hello') z dowolnego pliku i uzyskać tę samą konfigurację Winstona.
JHH

TypeError: (wartość pośrednia) nie jest funkcją
Urasquirrel

84

Powyższe odpowiedzi mi nie pomogły. W przypadku, gdy próbujesz dodać znacznik czasu do swoich dzienników przy użyciu najnowszej wersji Winston - 3.0.0-rc1, zadziałało to jak urok:

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

Użyłem „format.combine ()”. Ponieważ potrzebowałem sygnatury czasowej we wszystkich moich transportach, dodałem opcję formatowania w createLogger, a nie w każdym transporcie. Moje dane wyjściowe na konsoli i w pliku (activity.log) są następujące:

{"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"}

Możemy jak zwykle dodać formatowanie do tego znacznika czasu w „format.combine ()”, używając:

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

15

My też możemy to zrobić

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;

Czy to też działa logger.info('Message', someObject)? Skonfigurowałem niestandardowy format za pomocą kombajnu i nie mogę uzyskać tego someObjectw komunikacie dziennika.
Coś

1
Udało mi się someObjectdołączyć za pomocą poniższej instrukcji printf ${info.timestamp} [${info.level.toUpperCase()}]: ${info.message} ${JSON.stringify(info)}. Zawiera poziom, sygnaturę czasową i wiadomość, którą myślę, że mógłbym usunąć.
Coś

9

Można użyć wbudowanej util i zawsze osiągnąć rejestrowanie z timestap dla serwera nodejs. Po uruchomieniu serwera dodaj dane wyjściowe dziennika jako część parametru:

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

Następnie możesz napisać plik util w swoim pliku server.js

server.js

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

Wynik będzie wyglądał mniej więcej tak w pliku out.log:

out.log

15 Mar 15:09:28 - something with timestamp

1
Niestety util.error()pomija oznaczanie czasu wyjścia.
Saran,

4

Chociaż nie jestem świadomy winstona, jest to sugestia. używam log4js do rejestrowania, a moje dzienniki domyślnie wyglądają tak

[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'

Programowanie to środowisko procesu mojego węzła, a [INFO | FATAL] to poziom dziennika

W log4js możliwe jest utrzymywanie różnych profili logowania. Mam profile rozwoju i produkcji. Istnieją również typy loggerów, takie jak appender plików rolowanych, appender konsoli itp. Jako dodatek, pliki dziennika będą kolorowe w zależności od poziomu dziennika [Trace, Info, Debug, Error, Fatal];)

log4js zastąpi twój console.log. Jest to konfigurowalny parametr teraz w wersji 0.5+


FYI: Nowsze wersje log4js-node (0.5+) nie zastępują automatycznie console.log.
Jeff Hiltz,

@jeffhiltz Tak, masz rację :) Teraz jest to konfigurowalny parametr
Tamil


2

Czasami domyślny format sygnatury czasowej może być dla Ciebie niewygodny. Możesz zastąpić to swoją implementacją.

Zamiast

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

Możesz pisać

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

Zobacz https://github.com/winstonjs/winston#custom-log-format, aby uzyskać szczegółowe informacje


1

Innym rozwiązaniem jest umieszczenie rejestratora w pliku, który eksportuje niektóre funkcje, takie jak logger.info (), logger.error () itp., A następnie po prostu podajesz dodatkowy klucz do wysłania w każdym dzienniku komunikatów.

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
}

cokolwiek-plik.js

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

logger.info('Hello World!')

twój-log.log

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

1

Wziąłem odpowiedź Biswadeva i utworzyłem zestrunowany obiekt JSON. W ten sposób, jeśli będę musiał przetworzyć dzienniki później, będą one w dobrze zorganizowanym formacie.

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

Stosowanie:

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

Wynik:

Plik info.log:

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

Konsola:

info:    app is running on port 3001
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.