Fun with console.log() ๐Ÿ’ฟ

If you've ever developed a web app, you'll be familiar with console.log(...), the method which prints data to the developer console; useful for debugging, logging and testing.

Run console.log(console), and you'll see that there's much more to the console object.
This post briefly outlines the top 10 neat tricks you can use to level up your logging experience.

Contents


Tables

The console.table() method prints objects/ arrays as a neatly formatted tables.

console.table({
  'Time Stamp': new Date().getTime(),
  'OS': navigator['platform'],
  'Browser': navigator['appCodeName'],
  'Language': navigator['language'],
});

Screenshot showing an example output of console.table


Groups

Group related console statements together with collapsible sections, using console.group().

You can optionally give a section a title, by passing a string as the parameter. Sections can be collapsed and expanded in the console, but you can also have a section collapsed by default, by using groupCollapsed instead of group. You can also nest sub-sections within sections but be sure to remember to close out each group with groupEnd.

The following example will output an open section, containing some info

console.group('URL Info');
  console.log('Protocol', window.location.protocol);
  console.log('Host', window.origin);
  console.log('Path', window.location.pathname);
  console.groupCollapsed('Meta Info');
    console.log('Date Fetched', new Date().getTime());
    console.log('OS', navigator['platform']);
    console.log('Browser', navigator['appCodeName']);
    console.log('Language', navigator['language']);
  console.groupEnd();
console.groupEnd();

Screenshot showing an example output of console.group


Styled Logs

It's possible to style your log outputs with some basic CSS, such as colors, fonts, text styles and sizes. Note that browser support for this is quite variable.

For example, try running the following:

console.log(
  '%cHello World!',
  'color: #f709bb; font-family: sans-serif; text-decoration: underline;'
);

You should get the following output:

Screenshot showing an example using CSS in the console

Pretty cool, huh? Well there's a lot more you can do too!
Maybe change the font, style, background color, add some shadows and some curves...

Screenshot showing an example using CSS in the console

Here's something similar I'm using in a developer dashboard, the code is here

Screenshot showing an example using CSS in the console


Time

Another common debugging technique is measuring execution time, to track how long an operation takes. This can be achieved by starting a timer using console.time() and passing in a label, then ending the timer using console.timeEnd(), using the same label. You can also add markers within a long running operation using console.timeLog()

console.time("concatenation");
let output = "";
for (var i = 1; i <= 1e6; i++) {
  output += i;
}
console.timeEnd("concatenation");
concatenation: 1206ms - timer ended

Screenshot showing an example output of console.time

There's also a non-standard method, console.timeStamp() which adds markers within the performance tab, so you can correlate points in your code with the other events recorded in the timeline like paint and layout events.


Assert

You may only want to log to the console if an error occurs, or a certain condition is true or false. This can be done using console.assert(), which won't log anything to the console unless the first parameter is false.

The first parameter is a boolean condition to check, followed by 0 or more data points you'd like to print, and the last parameter is a message to output. So console.assert(false, 'Value was false') will output the message, since the first parameter is false.

const errorMsg = 'the # is not even';
for (let num = 2; num <= 5; num++) {
  console.log(`the # is ${num}`);
  console.assert(num % 2 === 0, { num }, errorMsg);
}

Screenshot showing an example output of console.assert


Count

Ever find yourself manually incrementing a number for logging? console.count() is helpful for keeping track how many times something was executed, or how often a block of code was entered.

You can optionally give your counter a label, which will let you manage multiple counters and make the output clearer.
Counters will always start from 1. You can reset a counter at anytime with console.countReset(), which also takes an optional label parameter.

The following code will increment the counter for each item in the array, the final value will be 8.

const numbers = [1, 2, 3, 30, 69, 120, 240, 420];
numbers.forEach((name) => {
  console.count();
});

The following is an example output of labelled counters.

Screenshot showing an example output of console.count

Instead of passing in a label, if you use a value, then you'll have a separate counter for each conditions value. For example:

console.count(NaN);         // NaN: 1
console.count(NaN+3);       // NaN: 2
console.count(1/0);         // Infinity: 1
console.count(String(1/0)); // Infinity: 2


Trace

In JavaScript, we're often working with deeply nested methods and objects. You can use console.trace() to traverse through the stack trace, and output which methods were called to get to a certain point.

Screenshot showing an example output of console.trace

You can optionally pass data to also be outputted along with the stacktrace.


Dir

If your logging a large object to the console, it may become hard to read. The console.dir() method will format it in an expandable tree structure.

The following is an example of a directory-style console output:

Screenshot showing an example output of console.dir

You can also print XML or HTML based trees in a similar way, by using console.dirxml().


Debug

You may have some logging set up within your app, that you rely on during development, but don't wish the user to see. Replacing log statements with console.debug() will do just this, it functions in exactly the same way as console.log but will be stripped out by most build systems, or disabled when running in production mode.


Log Levels

You may have noticed that there's several filters in the browser console (info, warnings and error), they allow you to change the verbosity of logged data. To make use of these filters, just switch out log statements with one of the following:

  • console.info() - Informational messages for logging purposes, commonly includes a small "i" and / or a blue background
  • console.warn() - Warnings / non-critical errors, commonly includes a triangular exclamation mark and / or yellow background
  • console.error() - Errors which may affect the functionality, commonly includes a circular exclamation mark and / or red background

In Node.js different log levels get written to different streams when running in production, for example error() will write to stderr, whereas log outputs to stdout, but during development they will all appear in the console as normal.


Multi-Value Logs

Most functions on the console object will accept multiple parameters, so you can add labels to your output, or print multiple data points at a time, for example: console.log('User: ', user.name);

But an easier approach for printing multiple, labelled values, is to make use of object deconstructing. For example, if you had three variables (e.g. x, y and z), you could log them as an object by surrounding them in curly braces, so that each variables name and value is outputted - like console.log( { x, y, z } );

Screenshot showing an example output of console deconstructing


Log String Formats

If you need to build formatted strings to output, you can do this with C-style printf using format specifiers.

The following specifiers are supported:

  • %s - String or any other type converted to string
  • %d / %i - Integer
  • %f - Float
  • %o - Use optimal formatting
  • %O - Use default formatting
  • %c - Use custom formatting (more info)

For example

console.log("Hello %s, welcome to the year %d!", "Alicia", new Date().getFullYear());
// Hello Alicia, welcome to the year 2022!

Of course, you could also use template literals to achieve the same thing, which might be easier to read for shorter strings.


Clear

Finally, when you're looking for an output from an event, you might want to get rid of everything logged to the console when the page first loaded. This can be done with console.clear(), which will clear all content, but nor reset any data.

It's usually also possible to clear the console by clicking the Bin icon, as well as to search through it using the Filter text input.


And some more...

There's so much more that you can do with logging to the console! For more info, check out the MDN console Documentation or the Chrome Dev Console Docs.

Just a quick note about best practices...

  • Define a lint rule, to prevent any console.log statements from being merged into your main branch
  • Write a wrapper function to handle logging, that way you can enable / disable debug logs based on environment, as well as use appropriate log levels, and apply any formatting. This can also be used to integrate with a third-party logging service with code updates only needed in a single place
  • Never log any sensitive info, the browser logs can be captured by any installed extensions, so should not be considered secure
  • Always use the correct log levels (like info, warn, error) to make filtering and disabling easier
  • Follow a consistent format, so logs can be parsed by a machine if needed
  • Write short, meaningful log messages always in English
  • Include the context or category within logs
  • Don't overdo it, only log useful info

You'll only receive email when they publish something new.

More from Alicia's Notes ๐Ÿš€
All posts