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.