We use cookies to improve your experience.

Effective JavaScript Logging Methods Beyond console.log

AG Software Development

4 minutes

Effective JavaScript Logging Methods Beyond console.log

We have all been there - something does not work right in our JavaScript / TypeScript code and we resort to our old friend, console.log. While this might work, there are better alternatives out there, especially when it comes to viewing complex objects, time or stack traces in the console.

Surely, there are better ways to debugging your code than throwing a ton of console.log statements. Using a debugger and stepping through the code will certainly provide the bigger picture, but this article is not about that - it is about the times when you need just a very quick peak into what is going on.

Let's dive right in!

console.trace

Sometimes, thing do not work as expected in the code - leaving us puzzled as to why we end up with X value instead of Y. Using console.trace helps us not only log the value specified, but also see the respective trace.

For instance, let's assume that we have the following code:

const firstFn = (a, b) => {
  console.trace(a, b);
  return (a + b) * 2;
};

const secondFn = (c) => {
  return firstFn(c, 2);
};

const thirdFn = (d) => {
  return secondFn(d);
};

const getResult = () => {
  const result = thirdFn(3);
  console.log(result);
};

getResult();

The console.trace statement in firstFn, will log for us both the a and b values, along with the stack trace.

console.group

Have you ever debugged a function with multiple console.log statements? Most of us have done so at some point. While this works by itself, we can leverage the console.group method, to effectively inline group our logging statements.

Take, for instance, the following code:

const getResult = (a, b) => {
  console.group('getResult flow');
  const sum = a + b;
  console.log('sum:', sum);
  const diff = a - b;
  console.log('diff:', diff);
  const product = a * b;
  console.log('product:', product);
  const quotient = a / b;
  console.log('quotient:', quotient);
  console.groupEnd();
};

As you see, we denote the starting point of the grouping with console.group and the end with console.groupEnd. Any logging statements between those two points will be logged as expected in the console. but indented.

console.count

Ever wondered how many times a given function is being invoked? Surely, you could just write something like console.log('fn called') and then count the logs, but console.count simplifies this for us.

const getResult = (a, b) => {
  console.count(`getResult called`);
  return a + b;
};

getResult(10, 5);
getResult(10, 5);
getResult(10, 5);
getResult(10, 5);
getResult(10, 5);

To have an even better understanding of how many times and where our function is being invoked, we can combine console.count with console.trace:

const getResult = (a, b) => {
  console.count(`getResult called`);
  console.trace();
  return a + b;
};

const firstFn = () => getResult(1, 2);
const secondFn = () => getResult(3, 4);
const thirdFn = () => getResult(5, 6);

firstFn();
firstFn();
secondFn();
secondFn();
thirdFn();

console.time

Sometimes, we may need to calculate how long a function invocation took. Maybe we are fetching some data, or maybe we are doing some heavy computations for whatever reason. Instead of using performance.now() before and after the function invocation, we can simply use console.time.

const getChuckNorrisJoke = async () => {
  const res = await fetch('https://api.chucknorris.io/jokes/random');
  const data = await res.json();
  return data;
};

console.time('Time taken');
getChuckNorrisJoke().then((res) => console.timeEnd('Time taken'));

console.table

Working with arrays is super frequent, regardless of whether you are building a website or an application. In the event that you are tempted to console.log an array, I would highly recommend using console.table instead, as it will print the data in a table format. Let's have a look, for instance, at the following code:

const userList = [
  { id: '1', username: 'Test1', branch: 'dev' },
  { id: '2', username: 'Test2', branch: 'dev' },
  { id: '3', username: 'Test3', branch: 'dev' },
  { id: '4', username: 'Test4', branch: 'dev' },
  { id: '5', username: 'Test5', branch: 'dev' },
  { id: '6', username: 'Test6', branch: 'dev' },
  { id: '7', username: 'Test7', branch: 'dev' },
  { id: '8', username: 'Test8', branch: 'dev' },
  { id: '9', username: 'Test9', branch: 'dev' },
  { id: '10', username: 'Test10', branch: 'dev' },
];

console.table(userList);
console.log(userList);

Where does this information leave us?

The console object provides a handful of methods, each with its own perks and quirks. While console.log might do the trick in many cases, we can always boost our productivity (or pretty-print something in a more fancy way) using a different method.

With that being said, it is also important to note that the console API might differ between runtimes. While this article does not cover all the available methods, I would highly recommend checking MDN for more information.

Thank you for taking the time to read this article. Happy coding!