Aggiunta di timestamp a tutti i messaggi della console


93

Ho un progetto completo, distribuito , basato su Express, con molte istruzioni console.log () e console.error () ovunque. Il progetto viene eseguito utilizzando per sempre, indirizzando stdout e stderr a 2 file separati.

Funziona tutto abbastanza bene, ma ora mi mancano i timestamp, per sapere esattamente quando si sono verificati gli errori.

Posso eseguire una sorta di ricerca / sostituzione in tutto il codice o utilizzare un modulo npm che sostituisce la console in ogni file, ma non voglio toccare ogni file di modello / percorso, a meno che non sia assolutamente necessario.

Esiste un modo, forse un middleware Express, che mi consenta di aggiungere un timestamp a ogni chiamata effettuata o devo aggiungerlo manualmente?


Risposte:


116

Si scopre che puoi sovrascrivere le funzioni della console nella parte superiore del file app.js e renderle effettive in ogni altro modulo. Ho ottenuto risultati contrastanti perché uno dei miei moduli è biforcato come file child_process. Una volta copiata anche la riga all'inizio di quel file, tutto funziona.

Per la cronaca, ho installato il modulo console-stamp ( npm install console-stamp --save) e ho aggiunto questa riga all'inizio di app.js e childProcess.js:

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

Il mio problema ora era che il :dateformato del logger di connessione utilizza il formato UTC, piuttosto che quello che sto usando nelle altre chiamate della console. Questo è stato facilmente risolto registrando il mio formato dell'ora (e come effetto collaterale, richiedendo il dateformatmodulo console stampfornito con, piuttosto che installarne un altro):

// 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'));

Ora i miei file di registro sembrano organizzati (e, meglio ancora, analizzabili):

[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
Non sono riuscito a trovare la documentazione, ma sembra che ": mm" si riferisca al mese e ": MM" è il formato che si desidera effettivamente utilizzare
Laurent Sigal

2
devi cambiare la parte dei minuti in base a quanto dice @ user603124. Per i minuti la stringa è : MM ( github.com/starak/node-console-stamp )
sucotronic

Grazie per il commento. Corretto!
Travelling Tech Guy

2
Sembra che non sia più necessario racchiudere HH: MM: ss.l tra parentesi - lo sta facendo automaticamente
Jeff

3
FYI loggerè stato sostituito da morgan github.com/senchalabs/connect#middleware
vtellier

34

modulo: "log-timestamp" funziona per me.

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

npm install log-timestamp

Semplice da usare

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

Risultato

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

26

Crea un file con quanto segue:

var log = console.log;

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

Richiedilo nella tua app prima di accedere a qualsiasi cosa. console.errorSe necessario, fai lo stesso .

Nota che questa soluzione distruggerà la variabile insertion ( console.log("he%s", "y") // "hey") se la stai usando. Se ne hai bisogno, registra prima il timestamp:

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

2
Non se è la stessa app / processo. La console è un oggetto globale quindi se si dirotta una delle sue funzioni in questo modo, continuerà a essere dirottata per tutti i file che condividono quell'oggetto globale.
Andreas Hultgren

Quindi questo dovrebbe / potrebbe essere inserito nel file app.js?
Travelling Tech Guy

1
Sì. <min 15 caratteri ...>
Andreas Hultgren

1
Consiglio invece di usare il timbro della console
Jacek Pietal,

1
Questa non è una buona soluzione: distrugge l'inserimento di variabili (quindi non può essere utilizzato come sostituzione) o stampa la data e l'output del registro su righe diverse.
George Y.

16

Se vuoi una soluzione senza un'altra dipendenza esterna ma vuoi mantenere tutte le funzionalità di console.log (parametri multipli, inserimento variabile) puoi usare il seguente codice:

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

È possibile modificare la funzione formatConsoleDate per formattare la data come si desidera.

Questo codice deve essere scritto solo una volta sopra il tuo file JavaScript principale.

console.log("he%s", "y") stamperà qualcosa del genere:

[12:22:55.053] hey

4
Grazie, questa risposta "nessuna dipendenza" era esattamente ciò di cui avevo bisogno.
RdR


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

2

Questa implementazione è semplice, supporta la funzionalità originale di console.log (passaggio di un singolo oggetto e sostituzione di variabili), non utilizza moduli esterni e stampa tutto in una singola chiamata a 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

Se lo desideri, puoi creare un logger personalizzato per la tua applicazione estendendo la build del nodo nella classe "Console". Si prega di fare riferimento alla seguente implementazione

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

Dopodiché, puoi usarlo nel tuo codice come:

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

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


1

Questa non è una risposta diretta, ma hai esaminato winston.js? Ha molte più opzioni di registrazione, inclusa la registrazione a un file o database json. Questi hanno sempre i timestamp per impostazione predefinita. Solo un pensiero.


Ho esaminato molte cose, in questo momento, vorrei aggiungere qualcosa a un progetto esistente e distribuito - senza toccare troppo il codice
Travelling Tech Guy


1

Sto provando a sovrascrivere l' consoleoggetto - sembra funzionare bene. Per utilizzarlo, salva il codice di seguito in un file, quindi importa per sovrascrivere l'oggetto proxy, quindi usalo normalmente.

(Nota che questo richiede il transpilation di babel e non funzionerà in ambienti che non supportano il Proxycostruttore JavaScript come 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],
  }
)

Fondamentalmente sovrascrivo l'oggetto console con un oggetto proxy JavaScript. Quando si chiama .log,.warn ecc., La console sovrascritta controllerà se ciò che stai chiamando è una funzione, in tal caso inserirà una data nell'istruzione di log come primo parametro, seguita da tutti i tuoi parametri.

Penso che l' consoleoggetto in realtà faccia molto e non lo capisco completamente. Così ho solo intercetta console.log, console.info, console.warn, console.errorchiama.


-1

Usa l'ascoltatore di eventi in questo modo,

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

buona codifica :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.