58

I have many console.log (or any other console calls) in my code and I would like to use them only when my app is in some kind of "debug mode".

I can't seem to use some kind of logger function and internally use console.log because then I wouldn't know what line fired it. Maybe only with a try/catch, but my logs are very general and I don't want try/catch in my code.

What would you recommend?

vsync
  • 118,978
  • 58
  • 307
  • 400

11 Answers11

60

I would probably abuse the short-circuiting nature of JavaScript's logical AND operator and replace instances of:

console.log("Foo.");

With:

DEBUG && console.log("Foo.");

Assuming DEBUG is a global variable that evaluates to true if debugging is enabled.

This strategy avoids neutering console.log(), so you can still call it in release mode if you really have to (e.g. to trace an issue that doesn't occur in debug mode).

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • yeah but I'll have to add this everywhere...it's lots of code :) – vsync Sep 21 '11 at 15:11
  • 1
    @vsync: Find & replace is your friend. Find 'console.log', replace with 'DEBUG && console.log'. But overriding console if debug is enabled (like in bjornd's answer), or replacing calls to console.log with a method you can easily override / replace is a neater method that requires less or no existing code edits. – cthulhu Sep 25 '11 at 19:27
  • 2
    `if (DEBUG) console.log("Foo.");` only two characters longer and much more readable. – Bergi Jun 20 '19 at 13:54
  • 1
    `const altConsole = { ...console }; console.log = (...data) => !environment.production && altConsole.log(...data);` – shrys Mar 13 '20 at 07:01
  • @shrys, what's that?!!! – danilo Aug 04 '20 at 18:38
51

Just replace the console.log with an empty function for production.

if (!DEBUG_MODE_ON) {
    console = console || {};
    console.log = function(){};
}
jagamot
  • 5,348
  • 18
  • 59
  • 96
bjornd
  • 22,397
  • 4
  • 57
  • 73
  • 9
    That's a hack. Your wasting computation in production – Raynos Sep 21 '11 at 13:58
  • 1
    @Raynos: SO is doing it as well. http://cdn.sstatic.net/js/stub.js Look at the empty function `StackExchange.debug.log`. I do agree it's a hack, though. – pimvdb Sep 21 '11 at 14:18
  • @pimvdb "Big company X is doing it wrong, this means I can do it wrong" – Raynos Sep 21 '11 at 14:20
  • 3
    @Raynos: No, as I said I agree about it being a hack. Just wanted to point that out :) – pimvdb Sep 21 '11 at 14:21
  • 7
    @Raynos Be real, calling an empty function several times is nothing in compare to the rest of the application, it's just a quick way to solve the problem. – bjornd Sep 21 '11 at 15:14
  • 2
    @bjornd Depends how much you log. It adds up. It's a hack. The cost of _using this hack_ is low, but so is the cost of fixing the hack. – Raynos Sep 21 '11 at 15:16
  • 20
    Yeah I see a lot of knee-jerk reactions to any extra processing from the mathematically-impaired. If you're doing 10^6 console.logs, there may still be a problem calling an empty function. Otherwise, a few hundred client-side calls to an empty function is nearly negligible. – Mason Houtz May 23 '12 at 13:17
  • 38
    @Raynos, "premature optimization is the root of all evil." Do you actually know any real case when this solution would noticeably degrade the performance? Have you done any benchmarks? I bet that the time spent on writing a batch script that removes all the logging (and never messes up the code) could be better invested... – Juliusz Gonera May 25 '12 at 23:53
  • Be careful. This appears to throw errors when using strict mode. – mattste Sep 08 '16 at 14:37
33

Clobbering global functions is generally a bad idea.

Instead, you could replace all instances of console.log in your code with LOG, and at the beginning of your code:

var LOG = debug ? console.log.bind(console) : function () {};

This will still show correct line numbers and also preserve the expected console.log function for third party stuff if needed.

namuol
  • 9,816
  • 6
  • 41
  • 54
  • 1
    You can avoid polluting the global namespace by adding such a log function to your site's namespace. For instance `myNamespace.log = myNamespace.DEBUG ? console.log : function(){};`. – Nick G. Mar 24 '14 at 17:38
  • @NickG. -- you need to use `Function::bind` like I do in my example for `console.log` to work -- otherwise you'll get a permissions exception when you try to execute it. – namuol Jul 22 '14 at 21:01
16

Since 2014, I simply use GULP (and recommend everyone to, it's an amazing tool), and I have a package installed which is called stripDebug which does that for you.

(I also use uglify and closureCompiler in production)


Update (June 20, 2019)

There's a Babel Macro that automatically removes all console statements:

https://www.npmjs.com/package/dev-console.macro

vsync
  • 118,978
  • 58
  • 307
  • 400
  • 4
    Noone will use the whole new building system **just** to deal with "console.log in production" problem. – bjornd Mar 27 '14 at 13:03
  • 1
    true, but a website that doesn't use any task manager such as GULP or GRUNT is probably far behind best-practices for web development. I want to encourage people to develop for the web in the proper way, which I truly believe that without task runner will most certainly be slower to maintain. – vsync Mar 27 '14 at 14:02
  • 1
    you can also run an NPM which just does that for you if you refuse to use GRUNT or GULP... – vsync Sep 01 '14 at 20:15
  • 1
    Anyone doing serious JS code for production should use some task runner to process the JS code, making it readable for development, and optimised for production - including stripping console.logs, comments etc. GULP and GRUNT are life savers. I'm up-voting this answer because it provides a solid solution that works in production and development. – Antonio Brandao Jul 17 '15 at 01:02
6

One more way to disable console.log in production and keep it in development.

// overriding console.log in production
if(window.location.host.indexOf('localhost:9000') < 0) {
    console.log = function(){};
}

You can change your development settings like localhost and port.

vinesh
  • 4,745
  • 6
  • 41
  • 45
3

This Tiny wrapper override will wrap the original console.log method with a function that has a check inside it, which you can control from the outside, deepening if you want to see console logs and not.

I chose window.allowConsole just as an example flag but in real-life use it would probably be something else. depending on your framework.

(function(cl){
  console.log = function(){
    if( window.allowConsole )
      cl(...arguments); 
  }
})(console.log)

Usage:

// in development (allow logging)
window.allowConsole = true;
console.log(1,[1,2,3],{a:1});

// in production (disallow logging)
window.allowConsole = false;
console.log(1,[1,2,3],{a:1});

This override should be implement as "high" as possible in the code hierarchy so it would "catch" all logs before then happen. This could be expanded to all the other console methods such as warn, time, dir and so on.

vsync
  • 118,978
  • 58
  • 307
  • 400
0

This code works for me:

if(console=='undefined' || !console || console==null) {
  var console = {
    log : function (string) {
        // nothing to do here!!
    }
  }
}
Himanshu
  • 31,810
  • 31
  • 111
  • 133
0

enter image description here

The newest versions of chrome show which line of code in which file fired console.log. If you are looking for a log management system, you can try out logeek it allows you to control which groups of logs you want to see.

Iman Mohamadi
  • 6,552
  • 3
  • 34
  • 33
0
// In Development:
var debugMode = true

// In Prod:
var debugMode = false

// This function logs console messages when debugMode is true .
function debugLog(logMessage) {
    if (debugMode) {
        console.log(logMessage);
    }
}

// Use the function instead of console.log
debugLog("This is a debug message");
deepakssn
  • 5,195
  • 2
  • 24
  • 19
0

console can out put not just log but errors warnings etc. Here is a function to override all console outputs

(function () {
    var method;
    var noop = function noop() { };
    var methods = [
    'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
    'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
    'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
    'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];
        console[method] = noop;
    }
}());

Refer to detailed post here https://stapp.space/disable-javascript-console-on-production/

Sachin Naik
  • 345
  • 2
  • 15
0

Simple.

Add a little bash script that finds all references to console.log and deletes them.

Make sure that this batch script runs as part of your deployment to production.

Don't shim out console.log as an empty function, that's a waste of computation and space.

Raynos
  • 166,823
  • 56
  • 351
  • 396