Mastering Console Logging

Alex R. Young





tutorials node modules

Mastering Console Logging

Posted by Alex R. Young on .

tutorials node modules

Mastering Console Logging

Posted by Alex R. Young on .

The console object crops up everywhere. But what is it, and what can it do? Most people seem to use it without realising the sheer convenience it can provide. Let's take a look at where it comes from, and how to use it correctly.

Built-in vs. Host

The console object is what's known as a host object in ECMAScript. Host objects are supplied by the host environment. Node's documentation refers to console as a "global object".

This is different to a native object which is an object in the ECMAScript implementation in question, and defined by the specification rather than the host environment. Built-in objects are similar, but are present when an ECMAScript program starts. In addition, built-in objects inherit from Object or Function whereas host objects might not.

Host objects may also not be available when execution starts. That's why some browsers treat console differently depending on whether the output is visible or not. Notice that Mozilla's documentation states that this behaviour has changed:

Prior to Gecko 12.0 (Firefox 12.0 / Thunderbird 12.0) , the console object's methods only work when the Web Console is open. Starting with Gecko 12.0, output is cached until the Web Console is opened, then displayed at that time.


Since console isn't yet formally covered by a specification, implementations vary. In Node it's closely tied to standard input output, referred to as "stdio" by the documentation. This gives rise to error and log methods that will be printed to the appropriate output stream.

Most implementations give us convenient ways of separating output for debugging messages, errors, and warnings:

console.log('This is merely an informational debug message');  
console.warn('This is a warning');  
console.error('This is an error');  

These messages will be handled differently depending on the environment. Firefox 10's built-in developer console will display an "X" next to the error, whereas Node will print to stderr.


Console redirection example

When writing Node scripts, it's a good idea to use console.error when displaying errors. It means that errors can be redirected in the shell -- sometimes I don't want to see standard output, but I do care about errors, so I'll redirect the errors into a log file.

I/O redirection generally works like this: 1> will redirect to stdout, and 2> redirects stderror. Given this example:

console.log('This is just noisy debug stuff');  
console.error('This means Alex broke something again');  

Then running node test.js 1> debug.log 2> errors.log will redirect the debug and error messages to separate files. Using 1> will truncate the file to a length of zero, so to append messages 1>> and 2>> can be used instead.

 Inspection and Concatenation

In most browsers and Node, objects will be automatically printed in a readable format when using console.log. That means printing variables is possible without any extra effort:

console.log({ alex: "some dude" });  

In Node, util.format is applied to the arguments, which runs util.inspect. Therefore, there's no need to run console.log(util.inspect(value)) in Node!

Most implementations will automatically concatenate values:

var name = 'Alex';  
console.log('Name:', name);  
// Name: Alex

Notice how a space is automatically added? There's no need to manually concatenate a value using console.log('Message: ' + value). In fact, doing this will mean the value won't be automatically inspected.

Node's format method uses Array.prototype.join to do this: lib/util.js.


Recent implementations also provide nascent string substitution support:

console.log('Name: %s, Intergalactic Credits: %d.', 'Alex', -100).  

Support for substitution strings isn't exactly printf yet, and with supporting between environments varying somewhat.


Both Node and Mozilla provide console.dir: Node runs util.inspect on the supplied argument and prints the output to stderr. Conversely, Firefox will display an interactive version of the object, with disclosure triangles if necessary.

Need to quickly benchmark a slow operation? The console.time and console.timeEnd methods can also be used in both environments. The time method accepts a parameter which allows the timer to be named:

for (var i = 0; i < 100; i++) {  

Stack traces can be displayed with console.trace(). Again, in Firefox this will be interactive, and in Node it'll be redirected to stderr.


The console object provides a surprisingly useful amount of functionality. If you're writing lightweight Node programs, or want to debug something in a relatively modern browser (or browser with suitable developer tools), then try to take advantage of it rather than relying on unnecessary libraries.

In general, when logging with console:

  • Use the correct logging method so redirection works as expected
  • Quickly append variables to messages using console.log('Message:', value)
  • Use console to automatically inspect variables