The following applies to console.[info|log|debug|warn|error]. Do not call it directly in public code; instead, wrap it in a logging utility.

The logging utility can be as simple as this:

function MyLogger(message) {
    console.log(message);
}

If you are going to include direct calls to console.log() in your application, use it sparingly and make the messages short and useful. Output of more than 140 characters dilutes the signal-to-noise ratio, which makes actual debugging calls to console.log() impractical.

console.log() is particularly helpful for debugging and/or troubleshooting when a debugger is not available, not convenient, or not appropriate (e.g. with async). In those situations, a call to console.log() lets us look at our application's runtime behavior.

To ensure that console.log() remains helpful, we should avoid pushing direct calls to version control, and we should definitely avoid direct calls to console.log() in production code. Why?

  • Stability. console.log() is a global that we cannot trust.
  • Security. console.log() can leak potentially sensitive data.
  • Developer Experience
    • Using console.log() widely reduces its signal-to-noise ratio.
    • Silencing or overriding console.log() is all-or-nothing.
    • Both hinder using console.log() for real, ad-hoc debugging.

Here are some more details on the poor developer experience that happens when we leave direct calls to console.log() in public code (where public code is either in production or in version control).

If we silence or override console.log() in production, then developers will have a hard time using it for real, ad-hoc troubleshooting. Have you ever edited production JavaScript source code in a browser or in a Node application? Writing a console.log(someVar) helps to see what is happening. If we silence the console, then this useful tool is not available. On the other hand, if we do not silence it, and if we have it widely in our production code, then the low signal-to-noise ratio makes console.log() impractical to use.

The above is an argument for removing console.log() from production code. What about development code? Using console.log() is only fine if we keep it out of version control. Otherwise our own calls to console.log() will make it hard for other developers to find their calls to console.log(). Further, if we silence or override console.log() in unit/integration tests, then the output from those tests disappears: we no longer see the useful 17 passing / 3 failing (36s) messages after running our tests, nor do we see which tests are passing or failing.

The solution: Write a logging utility that wraps console. Do not push direct calls to console.log() into version control or into production code. All calls go through that logging utility, because the only place console.log() appears is in that logging utility file. console.log() is a specific logging provider not a general logging abstraction; use it accordingly.

Thoughts? Talk to me @dicshaunary on Twitter..


Edit: Some have noted that big applications such as Slack use console.log() in production. They use it predominantly through a wrapper.

  1. It's very rare to see a message longer that 140 characters.
  2. It's very rarely to call console.log directly. For instance, Slack's rollup-secondary_a_required.js file is 51,196 lines of JavaScript. The term console appears 119 times in 72 of those lines. All of those lines involve a call to TS.console.log().

Note: this is the regex we used to find those stats: ^(?=.*console)(?=.*TS).*.