Adding timestamps to all console messages

I have a complete, deployed, Express-based project, with many console.log() and console.error() statements throughout. The project runs using forever, directing the stdout and stderr to 2 separate files.

It all works quite well, but now I'm missing timestamps - to know exactly when errors occurred.

I can do some kind of search/replace throughout my code, or use some npm module that overrides console in each file, but I do not want to touch every model/route file, unless I absolutely have to.

Is there a way, perhaps an Express middleware, that would allow me to add a timestamp to every call made, or do I have to manually add it?

Answers


It turns out, you can override the console functions at the top of the app.js file, and have it take effect in every other module. I got mixed results because one of my modules is forked as a child_process. Once I copied the line to the top of that file as well, all works.

For the record, I installed the module console-stamp (npm install console-stamp --save), and added this line to the top of app.js and childProcess.js:

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

My problem now was that the :date format of the connect logger uses UTC format, rather than the one I'm using in the other console calls. That was easily fixed by registering my own time format (and as a side effect, requiring the dateformat module that console stamp comes with, rather than installing another one):

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

Now my log files look organized (and better yet, parseable):

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

Create a file with the following:

var log = console.log;

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

Require it in your app before you log anything. Do the same for console.error if needed.

Note that this solution will destroy variable insertion (console.log("he%s", "y") // "hey") if you're using that. If you need that, just log the timestamp first:

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

module: "log-timestamp" works for me.

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

npm install log-timestamp

Simple to use

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

Result

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

You could also use the log-timestamp package. It's quite straightforward, and customizable as well.


If you want a solution without another external dependency but you want to keep the full functionalities of console.log (multiple parameters, variable insertion) you can use the following code:

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

You can modify the formatConsoleDate function to format the date how you want.

This code needs to be written only once on top of your main JavaScript file.

console.log("he%s", "y") will print something like this:

[12:22:55.053] hey

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

This isn't a direct answer, but have you looked into winston.js? It has a ton more logging options including logging to a json file or database. These always have timestamps by default. Just a thought.


You can use a function util.log from https://nodejs.org/api/util.html.


This implementation is simple, supports original functionality of console.log (passing a single object, and variable substitution), doesn't use external modules and prints everything in a single call to 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 );
};

Need Your Help

HTML5 Canvas Transformation Matrix

javascript html5 canvas

I don't understand what the Transformation Matrix is and how to work with it.

string.ToLower() and string.ToLowerInvariant()

c# .net string

What's the difference and when to use what? What's the risk if I always use ToLower() and what's the risk if I always use ToLowerInvariant()?