Intercept calls to console.log in Chrome

I have a script that I can't change that makes a lot of console.log calls. I want to add another layer and respond if the calls contain certain strings. This works in Firefox, but throws an "Illegal invocation" error in Chrome on the 4th line:

var oldConsole = {};
oldConsole.log = console.log;
console.log = function (arg) {
    oldConsole.log('MY CONSOLE!!');
    oldConsole.log(arg);
}

Any ideas how to get around that? I also tried cloning the console...


Solution 1:

You need to call console.log in the context of console for chrome:

(function () {
  var log = console.log;
  console.log = function () {
    log.call(this, 'My Console!!!');
    log.apply(this, Array.prototype.slice.call(arguments));
  };
}());

Modern language features can significantly simplify this snippet:

{
  const log = console.log.bind(console)
  console.log = (...args) => {
    log('My Console!!!')
    log(...args)
  }
}

Solution 2:

I know it's an old post but it can be useful anyway as others solution are not compatible with older browsers.

You can redefine the behavior of each function of the console (and for all browsers) like this:

// define a new console
var console = (function(oldCons){
    return {
        log: function(text){
            oldCons.log(text);
            // Your code
        },
        info: function (text) {
            oldCons.info(text);
            // Your code
        },
        warn: function (text) {
            oldCons.warn(text);
            // Your code
        },
        error: function (text) {
            oldCons.error(text);
            // Your code
        }
    };
}(window.console));

//Then redefine the old console
window.console = console;

Solution 3:

You can also use the same logic, but call it off the console object so the context is the same.

if(window.console){
  console.yo = console.log;
  console.log = function(str){
    console.yo('MY CONSOLE!!');
    console.yo(str);
  }
}

Solution 4:

With ES6 new spread operator you can write it like this

(function () {
  var log = console.log;
  console.log = function () {
    log.call(this, 'My Console!!!', ...arguments);
  };
}());

Solution 5:

Can be simply:

console.log = (m) => terminal.innerHTML = JSON.stringify(m)
#terminal {background: black; color:chartreuse}
$ > <span id="terminal"></span>
<hr>        
<button onclick="console.log('Hello world!!')">3V3L</button>
<button onclick="console.log(document)">3V3L</button>
<button onclick="console.log(Math.PI)">3V3L</button>