Reputation: 549
I want to override console.log
method to invoke a set of tasks whenever console.log
is called. I referred other Stackoverflow answers but that give me the error:
Uncaught RangeError: Maximum call stack size exceeded.
This is what I want to do:
backupconsolelog = console.log;
console.log = function(arguments)
{
//do my tasks;
backupconsolelog(arguments);
}
Update 1: Somehow managed to over-ride console.log successfully, but I'm now unable to execute console.log(displaySomethingInConsole)
in the same .js file where over-riding is done. This somehow causes recursive call to console.log
, and gives again Uncaught RangeError: Maximum call stack size exceeded.
How do I use console.log() in the same .js file?
Update 2: I've have a check()
function which is called by over-rided console.log
. But, there was a console.log
call inside the check()
function which caused Maximum call stack size exceeded.
error.
Update 3: Error again! :(
Uncaught TypeError: Illegal invocation
var _log = window.console.log;
window.console.log = function () {
_log.apply(this, arguments);
check();
};
_log("aaa");
check() {};
Update 4: Binding console
to _log
, i.e., console.log.bind(console)
cleared it.
Upvotes: 3
Views: 7455
Reputation: 1897
The accepted answers will work with the provided structure EXCEPT in cases where you will need to "setup" the override multiple times on a running instance for example. If you have a live container, or a lambda function, you run the risk of the arguments array building up upon itself.
[ arg1 ] -> [ [arg1] , arg2 ] -> [ [ [ arg1 ] , arg2] , arg3 ]
Ex:
function x(){
var log = console.log;
console.log = function () {
var args = Array.from(arguments);
args.push('post fix');
log.apply(console, args);
}
}
new x()
console.log(1)
new x()
console.log(2)
OUTPUTS:
1 post fix
2 post fix post fix
SOLUTIONS:
Make sure if you need to use this function as middleware for example, you maintain the reference outside of the middleware function like:
var log = console.log;
function x(){
console.log = function () {
var args = Array.from(arguments);
args.push('post fix');
log.apply(console, args);
}
}
new x()
console.log(1)
new x()
console.log(2)
OUTPUTS:
1 post fix
2 post fix
OR better yet...
const log = console.log;
function middleWare() {
console.log = (...args) => {
log(...args, 'post fix');
}
}
Upvotes: 0
Reputation: 410
This works for me.
let originalConsole = Object.assign({}, console);
console.log = (value) => {
//some cool condition
if (true) {
value = "new_log : " + value
}
originalConsole.log(value);
};
Upvotes: 0
Reputation: 851
After some problems, I managed to get console.log replacement with winston + express to work.
I use winston-sugar as it makes configuration easier but anything should work. (.config/winston.json is created when you do npm install winston-sugar) People wanting to replace console.log with something else can just look at the last 5 lines as it gives very clean code.
I think this is a very neat way to get express logged into files along with console.log
const morgan = require('morgan');
const winstonLoader = require('winston-sugar');
winstonLoader.config('./config/winston.json');
const log = winstonLoader.getLogger('app');
log.stream = {
write: function (message, encoding) {
log.info(message);
},
};
// Add some lines indicating that the program started to track restarts.
log.info('----------------------------------');
log.info('--');
log.info('-- Starting program');
log.info('--');
log.info('----------------------------------');
console.log = (...args) => log.info(...args);
console.info = (...args) => log.info(...args);
console.warn = (...args) => log.warn(...args);
console.error = (...args) => log.error(...args);
console.debug = (...args) => log.debug(...args);
And later in the code if you are running express.
// app.use(morgan('combined')); //replaced with the next line to get morgan logs into the winston logfiles.
app.use(morgan('combined', { stream: log.stream }));
Upvotes: 2
Reputation: 19305
If you get a Maximum call stack size exceeded error, it almost definitely means your function is recursively calling itself infinitely. The solution you have found, and the one RaraituL has shown, should work perfectly. You are probably calling the part of your code that sets up the call redirection more than once.
// First time:
backupconsolelog = console.log.bind(console);
console.log = function() {
backupconsolelog.apply(this, arguments);
/* Do other stuff */
}
// console.log is now redirected correctly
// Second time:
backupconsolelog = console.log;
// Congratulations, you now have infinite recursion
You could add some debugging information (not using console.log
, obviously, try debugger;
instead to create an automatic breakpoint) where you set up the redirection to see where and when your code is called.
UPDATE
This might belong in a comment: Your console.log
redirection function calls some function called check
, apparently. This check
function then calls console.log
, which if your function - not the original one. Have the check
function call the original implementation instead.
backupconsolelog = console.log.bind(console);
console.log = function() {
check();
backupconsolelog.apply(this, arguments);
}
function check() {
// This will call your function above, so don't do it!
console.log('Foo');
// Instead call the browser's original implementation:
backupconsolelog('Foo');
}
UPDATE 2
The inner workings of the brower's console.log
implementation may or may not depend on the console
being set for the this
reference. Because of this, you should store console.log
bound to console
, like in my code.
Upvotes: 5
Reputation: 92
You probably need to bind original method to console:
var old = console.log.bind(console)
console.log = (...args) => {
// perform task
alert('test')
old.apply(null, args)
}
Upvotes: 0
Reputation: 11721
// keep reference to original function
var _log = window.console.log;
// overwrite function
window.console.log = function () {
_log.apply(this, arguments);
alert(arguments);
};
console.log("hello world");
Upvotes: 4