Ajout d'horodatages à tous les messages de la console


93

J'ai un projet complet, déployé , basé sur Express, avec de nombreuses instructions console.log () et console.error () partout. Le projet s'exécute en utilisant forever, dirigeant le stdout et le stderr vers 2 fichiers séparés.

Tout fonctionne très bien, mais il me manque maintenant des horodatages - pour savoir exactement quand des erreurs se sont produites.

Je peux faire une sorte de recherche / remplacement dans tout mon code, ou utiliser un module npm qui remplace la console dans chaque fichier, mais je ne veux pas toucher à chaque fichier de modèle / route, sauf si je dois absolument le faire.

Existe-t-il un moyen, peut-être un middleware Express, qui me permettrait d'ajouter un horodatage à chaque appel effectué, ou dois-je l'ajouter manuellement?


Réponses:


116

Il s'avère que vous pouvez remplacer les fonctions de la console en haut du fichier app.js et les faire appliquer dans tous les autres modules. J'ai obtenu des résultats mitigés car l'un de mes modules est forké en tant que fichier child_process. Une fois que j'ai copié la ligne en haut de ce fichier, tout fonctionne.

Pour mémoire, j'ai installé le module console-stamp ( npm install console-stamp --save), et ajouté cette ligne en haut de app.js et childProcess.js:

// add timestamps in front of log messages
require('console-stamp')(console, '[HH:MM:ss.l]');

Mon problème était maintenant que le :dateformat de l'enregistreur de connexion utilise le format UTC, plutôt que celui que j'utilise dans les autres appels de console. Cela a été facilement résolu en enregistrant mon propre format d'heure (et en tant qu'effet secondaire, nécessitant le dateformatmodule console stampfourni avec, plutôt que d'en installer un autre):

// since logger only returns a UTC version of date, I'm defining my own date format - using an internal module from console-stamp
express.logger.format('mydate', function() {
    var df = require('console-stamp/node_modules/dateformat');
    return df(new Date(), 'HH:MM:ss.l');
});
app.use(express.logger('[:mydate] :method :url :status :res[content-length] - :remote-addr - :response-time ms'));

Maintenant, mes fichiers journaux semblent organisés (et mieux encore, analysables):

[15:09:47.746] staging server listening on port 3000
[15:09:49.322] connected to database server xxxxx successfully
[15:09:52.743] GET /product 200 - - 127.0.0.1 - 214 ms
[15:09:52.929] GET /stylesheets/bootstrap-cerulean.min.css 304 - - 127.0.0.1 - 8 ms
[15:09:52.935] GET /javascripts/vendor/require.js 304 - - 127.0.0.1 - 3 ms
[15:09:53.085] GET /javascripts/product.js 304 - - 127.0.0.1 - 2 ms
...

2
Je n'ai pas pu trouver la documentation pour cela, mais il semble que ": mm" fera référence au mois, et ": MM" est le format que vous voulez réellement utiliser
Laurent Sigal

2
vous devriez changer la partie des minutes selon ce que dit @ user603124. Pendant des minutes, la chaîne est : MM ( github.com/starak/node-console-stamp )
sucotronic

Merci pour le commentaire. Corrigée!
Travelling Tech Guy

2
On dirait que vous n'avez plus besoin de mettre HH: MM: ss.l entre crochets - il le fait automatiquement
Jeff

3
FYI loggera été remplacé par morgan github.com/senchalabs/connect#middleware
vtellier

34

module: "log-timestamp" fonctionne pour moi.

voir https://www.npmjs.com/package/log-timestamp

npm install log-timestamp

Utilisation simple

console.log('Before log-timestamp');
require('log-timestamp');
console.log('After log-timestamp');

Résultat

Before log-timestamp
[2012-08-23T20:08:32.000Z] After log-timestamp

26

Créez un fichier avec les éléments suivants:

var log = console.log;

console.log = function(){
  log.apply(console, [Date.now()].concat(arguments));
};

Exigez-le dans votre application avant de vous connecter. Faites de même console.errorsi nécessaire.

Notez que cette solution détruira l'insertion de variable ( console.log("he%s", "y") // "hey") si vous l'utilisez. Si vous en avez besoin, enregistrez d'abord l'horodatage:

log.call(console, Date.now());
log.apply(console, arguments);

2
Pas si c'est la même application / processus. La console est un objet global, donc si vous détournez une de ses fonctions comme celle-ci, elle continuera d'être détournée pour tous les fichiers qui partagent cet objet global.
Andreas Hultgren

Donc, cela devrait / pourrait être placé dans le fichier app.js?
Travelling Tech Guy

1
Oui. <min 15 chars ...>
Andreas Hultgren

1
Je recommande d'utiliser plutôt le tampon de la console
Jacek Pietal

1
Ce n'est pas une bonne solution - cela détruit l'insertion de variable (ne peut donc pas être utilisé comme remplacement), ou imprime la date et la sortie du journal sur différentes lignes.
George Y.14

16

Si vous souhaitez une solution sans autre dépendance externe mais que vous souhaitez conserver toutes les fonctionnalités de console.log (paramètres multiples, insertion de variables) vous pouvez utiliser le code suivant:

var log = console.log;

console.log = function () {
    var first_parameter = arguments[0];
    var other_parameters = Array.prototype.slice.call(arguments, 1);

    function formatConsoleDate (date) {
        var hour = date.getHours();
        var minutes = date.getMinutes();
        var seconds = date.getSeconds();
        var milliseconds = date.getMilliseconds();

        return '[' +
               ((hour < 10) ? '0' + hour: hour) +
               ':' +
               ((minutes < 10) ? '0' + minutes: minutes) +
               ':' +
               ((seconds < 10) ? '0' + seconds: seconds) +
               '.' +
               ('00' + milliseconds).slice(-3) +
               '] ';
    }

    log.apply(console, [formatConsoleDate(new Date()) + first_parameter].concat(other_parameters));
};

Vous pouvez modifier la fonction formatConsoleDate pour formater la date comme vous le souhaitez.

Ce code ne doit être écrit qu'une seule fois par-dessus votre fichier JavaScript principal.

console.log("he%s", "y") affichera quelque chose comme ceci:

[12:22:55.053] hey

4
Merci, cette réponse "pas de dépendances" était exactement ce dont j'avais besoin.
RdR


3
app.use(morgan('[:date[web]] :method :url :status :res[content-length] - :remote-addr - :response-time ms'))

2

Cette implémentation est simple, prend en charge la fonctionnalité originale de console.log (passage d'un seul objet et substitution de variable), n'utilise pas de modules externes et imprime tout en un seul appel à console.log:

var origlog = console.log;

console.log = function( obj, ...placeholders ){
    if ( typeof obj === 'string' )
        placeholders.unshift( Date.now() + " " + obj );
    else
    {
        // This handles console.log( object )
        placeholders.unshift( obj );
        placeholders.unshift( Date.now() + " %j" );
    }

    origlog.apply( this, placeholders );
};

2

Si vous le souhaitez, vous pouvez créer un enregistreur personnalisé pour votre application en étendant la construction du nœud dans la classe «Console». Veuillez vous référer à la mise en œuvre suivante

"use strict";

const moment = require('moment');
const util = require('util');
const Console = require('console').Console;

class Logger extends Console {
    constructor(stdout, stderr, ...otherArgs) {
        super(stdout, stderr, ...otherArgs);
    }

    log(...args) {
        super.log(moment().format('D MMM HH:mm:ss'), '-', util.format(...args));
    }

    error(...args) {
        super.error(moment().format('D MMM HH:mm:ss'), '-', util.format(...args));
    }
}

module.exports = (function() {
    return new Logger(process.stdout, process.stderr); 
}());

Après cela, vous pouvez l'utiliser dans votre code comme:

const logger = require('./logger');

logger.log('hello world', 123456);
logger.error('some error occurred', err);


1

Ce n'est pas une réponse directe, mais avez-vous examiné winston.js? Il a une tonne d'options de journalisation supplémentaires, notamment la journalisation dans un fichier ou une base de données json. Ceux-ci ont toujours des horodatages par défaut. Juste une pensée.


J'ai examiné beaucoup de choses, en ce moment, j'aimerais ajouter quelque chose à un projet existant et déployé - sans trop toucher au code
Travelling Tech Guy


1

J'essaye d'écraser l' consoleobjet - semble bien fonctionner. Pour l'utiliser, enregistrez le code ci-dessous dans un fichier, puis importez-le pour écraser l'objet proxy, puis utilisez-le normalement.

(Notez que cela nécessite une transpilation babel et ne fonctionnera pas dans des environnements qui ne prennent pas en charge le Proxyconstructeur JavaScript tel que IE 11).

import console from './console-shadow.js'

console.log(...)
console.warn(...)
console.error(...)
// console-shadow.js

// Only these functions are shadowed by default
const overwrites = ['log', 'warn', 'info', 'error']

export default new Proxy(
  // Proxy (overwrite console methods here)
  {},

  // Handler
  {
    get: (obj, prop) =>
      prop in obj
        ? obj[prop]
        : overwrites.includes(prop)
        ? (...args) => console[prop].call(console, new Date(), ...args)
        : console[prop],
  }
)

Fondamentalement, je remplace l'objet console par un objet proxy JavaScript. Lorsque vous appelez .log, .warnetc. la console écrasée vérifie si ce que vous appelez est une fonction, le cas échéant , il injectera une date dans la déclaration de journal comme premier paramètre, suivi de tous vos paramètres.

Je pense que l' consoleobjet fait beaucoup et je ne le comprends pas complètement. Donc , je ne intercepter console.log, console.info, console.warn, console.errorappelle.


-1

Utilisez un écouteur d'événements comme celui-ci,

process.on('error', function() { 
   console.log('Error Occurred.');

   var d = Date(Date.now()).toString();
   console.log.call(console, d); // Wed Aug 07 2019 23:40:07 GMT+0100 (GMT+01:00)
});

bon codage :)

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.