Comment puis-je ajouter un horodatage aux journaux à l'aide de la bibliothèque Node.js Winston?


93

Je souhaite ajouter un horodatage aux journaux. Quelle est la meilleure façon d'y parvenir?


Cela reste trop large car vous ne pouvez PAS le faire à partir de la machine cliente.
Joshua

Réponses:


112

J'étais moi-même confronté au même problème. J'ai pu le faire de deux manières.

Lorsque vous incluez Winston, il ajoute généralement par défaut un transport de console. Pour que les horodatages fonctionnent dans ce cas par défaut, je devais soit:

  1. Supprimez le transport de console et ajoutez à nouveau avec l'option d'horodatage.
  2. Créez votre propre objet Logger avec l'option d'horodatage définie sur true.

La première:

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

La deuxième option, plus propre:

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

Certaines des autres options pour le transport de la console peuvent être trouvées ici :

  • level: Niveau des messages que ce transport doit consigner («debug» par défaut).
  • silent: indicateur booléen indiquant s'il faut supprimer la sortie (false par défaut).
  • colorize: indicateur booléen indiquant si nous devons coloriser la sortie (false par défaut).
  • horodatage: indicateur booléen indiquant si nous devons ajouter au début la sortie avec des horodatages (faux par défaut). Si la fonction est spécifiée, sa valeur de retour sera utilisée à la place des horodatages.

1
Incroyable et simple à la fois. Je vous remercie!
kolrie

7
C'est bien. J'emballe habituellement ceci dans un fichier dédié afin que je puisse facilement obtenir mon enregistreur configuré à partir de n'importe quel fichier, c'est-à-dire que je mets le code ci-dessus (option 2) dans un nouveau fichier logger.js, suivi de module.exports = logger; puis à partir de n'importe quel fichier, je fais var logger = require ('./ logger.js') et je peux ensuite faire logger.info ('hello') à partir de n'importe quel fichier et obtenir la même configuration de Winston.
JHH

TypeError: (valeur intermédiaire) n'est pas une fonction
Urasquirrel

81

Les réponses ci-dessus n'ont pas fonctionné pour moi. Si vous essayez d'ajouter un horodatage à vos journaux en utilisant la dernière version de Winston - 3.0.0-rc1, cela a fonctionné comme un charme:

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

J'ai utilisé 'format.combine ()'. Comme j'avais besoin d'un horodatage sur tous mes transports, j'ai ajouté l'option de formatage dans createLogger, plutôt qu'à l'intérieur de chaque transport. Ma sortie sur console et sur fichier (activity.log) est la suivante:

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

Nous pouvons ajouter un formatage à cet horodatage dans 'format.combine ()' comme d'habitude en utilisant:

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

14

On peut faire comme ça aussi

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;

Cela fonctionne-t-il aussi pour logger.info('Message', someObject)? J'ai configuré un format personnalisé à l'aide de la combinaison et je n'arrive pas à obtenir l' someObjectinclusion dans le message du journal.
SomethingOn

1
J'ai pu être someObjectinclus en utilisant l'instruction printf suivante ${info.timestamp} [${info.level.toUpperCase()}]: ${info.message} ${JSON.stringify(info)}. Il comprend le niveau, l'horodatage et le message que je suppose que je pourrais supprimer.
SomethingOn

9

Vous pouvez utiliser intégré util et toujours pour réaliser l' enregistrement avec timestap pour votre serveur nodejs. Lorsque vous démarrez un serveur, ajoutez une sortie de journal dans le cadre du paramètre:

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

Et puis vous pouvez écrire util dans votre server.js

server.js

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

La sortie ressemblera à quelque chose comme ceci dans le fichier out.log:

out.log

15 Mar 15:09:28 - something with timestamp

1
Malheureusement, util.error()ignore l'horodatage de la sortie.
Saran

4

Bien que je ne connaisse pas winston, ceci est une suggestion. J'utilise log4js pour la journalisation et mes journaux par défaut ressemblent à ceci

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

Le développement est l'environnement de mon processus de nœud et [INFO | FATAL] est au niveau du journal

La gestion de différents profils pour la journalisation est possible dans log4js. J'ai des profils de développement et de production. Il existe également des types d'enregistreurs tels que l'appendeur de fichier roulant, l'appendeur de console, etc. En tant qu'addon, vos fichiers journaux seront colorés en fonction du niveau de journal [Trace, Info, Debug, Error, Fatal];)

log4js remplacera votre console.log C'est un paramètre configurable maintenant dans 0.5+


Pour info: les nouvelles versions de log4js-node (0.5+) ne remplacent pas automatiquement console.log.
Jeff Hiltz

@jeffhiltz Ya vous avez raison :) Maintenant, c'est un paramètre configurable
Tamil

2

Parfois, le format d'horodatage par défaut peut ne pas vous convenir. Vous pouvez le remplacer avec votre implémentation.

Au lieu de

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

tu peux écrire

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

Voir https://github.com/winstonjs/winston#custom-log-format pour les détails



0

Une autre solution consiste à envelopper le logger dans un fichier qui exporte certaines fonctions comme logger.info (), logger.error (), etc., puis il vous suffit de passer une clé supplémentaire à envoyer sur chaque journal de messages.

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
}

quel que soit le fichier.js

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

logger.info('Hello World!')

votre-log.log

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

0

J'ai pris la réponse de Biswadev et créé un objet JSON stringifié. De cette façon, si je dois traiter les journaux plus tard, ce sera dans un format bien structuré.

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

Usage:

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

Production:

Fichier info.log:

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

Console:

info:    app is running on port 3001
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.