DEV Community

Manuel Heidrich
Manuel Heidrich

Posted on • Originally published at

A hassle-free, zero dependency way to handle console.log() & co. in a production Angular application

console.log() and its siblings likely are the most used methods any JavaScript developer has ever used. And that‘s totally fine, because console.log() most definitely is a huge help if not even a life saver when debugging an application.

And there is the challenge right there: as helpful as output in the browser‘s console is when debugging, it is absolutely not a good idea to leave this output when deploying your application to production. At least any output below the error level.

So one solution could be to not leave any console methods in the code (except maybe console.error()). Fortunately linters like tslint or eslint have built-in rules to help you with that. But let‘s be honest, we developers usually are lazy af. Also often there are situations where we want to have console output permanently when developing. So it would be a huge hassle to add, remove, re-add (and so on) the console methods.

I wrote about a custom logger service a couple of years ago, which is environment agnostic, but I’m no longer using it. The main reason is that you are not able to see the file and line the output was generated. Plus I do not always want to import and inject a service first. Using console.log() is just so much more convenient.

My solution

For my current side project Monitornator I added a method called handleConsole() to my AppComponent that looks like this:

private handleConsole(): void {
  let methods: string[] = [];

  switch ( {
    case production:
    case staging:
      methods = [log, debug, info, warn];


  if (methods.length) {
    console.warn(`🚨 Console output is disabled on ${}!`);

  methods.forEach((method) => {
    console[method] = function(): void { };
Enter fullscreen mode Exit fullscreen mode

What it does is basically overriding any console method with an empty function, depending on the current environment. So leaving console.log() in the code in this case will just print nothing while on staging or production.
Using switch case allows me to quickly add different log levels for different environments.
And before overriding the methods I print a warning to the console, because... let’s say SOMEONE more then once spent a huge amount of time wondering why console.log() suddenly stopped working while on staging 🤦🏼‍♂️.


Of course there is a fair amount of logging libraries out there, some better than others, but I personally don’t want to add another dependency for something I can solve with just a couple lines of code. The above solution works pretty fine for me.

Top comments (2)

devmyqi profile image
Michael Wronna • Edited

Thanks Manuel,

logging is always the first feature I implement, I mostly use a own function like:

const log = function(level,message) {
  const logdate = function() {
    const date = new Date();
    return String(date.getHours()).padStart(2,'0') + ':'
      + String(date.getMinutes()).padStart(2,'0') + ':'
      + String(date.getSeconds()).padStart(2,'0') + '.'
      + String(date.getMilliseconds()).padStart(3,'0');
    const logtype = function(level) {
      const logtypes = {1:'info',2:'info',4:'info',8:'warning',
      return logtypes[level] ? logtypes[level] : 'undef';
   if ( config.loglevel & level ) {
     console.log(`${logdate()} [${logtype(level)}] (${level}) ${message}`);

Sometimes, especially for client code I extend this function with:

  // inside log function
  const logcmd = function(level) {
    if ( level === 8 ) { return 'warn';
    } else if ( level === 16 ) { return 'error';
    } else { return 'log'; }
  // and then log with
  console[logcmd(level)]('the log string');
mahnuh profile image
Manuel Heidrich

Sure, in the case above that would absolutely work! I chose not to shorten it for readability and the ability to add different log levels for production and staging for example.