I ran into this issue as well about extending console.log() so that the application can extend, control and do fancy stuff with it in addition to logging stuff to the console. Losing the line number information was tantamount to failure, however. After wrestling with the issue, I came up with a long-winded workaround, but at least it's still a "1-liner" to use.
First, define a global class to use or add some methods to your main existing "app" class:
/**
* Log message to our in-app and possibly on-screen console, return args.
* @param {!string} aMsgLevel - one of "log", "debug", "info", "warn", or "error"
* @param {any} aArgs - the arguments to log (not used directly, just documentation helper)
* @returns args so it can be nested within a console.log.apply(console,app.log()) statement.
*/
MyGlobalClassWithLogMethods.prototype.debugLog = function(aMsgLevel, aArgs) {
var s = '';
var args = [];
for (var i=1; i<arguments.length; i++) {
args.push(arguments[i]);
if (arguments[i])
s += arguments[i].toString()+' ';
}
if (typeof this.mLog === 'undefined')
this.mLog = [];
this.mLog.push({level: aMsgLevel, msg: s});
return args;
};
MyGlobalClassWithLogMethods.prototype.log = function() {
var args = ['log'].concat(Array.prototype.slice.call(arguments));
return this.debugLog.apply(this,args);
};
MyGlobalClassWithLogMethods.prototype.debug = function() {
var args = ['debug'].concat(Array.prototype.slice.call(arguments));
return this.debugLog.apply(this,args);
};
MyGlobalClassWithLogMethods.prototype.info = function() {
var args = ['info'].concat(Array.prototype.slice.call(arguments));
return this.debugLog.apply(this,args);
};
MyGlobalClassWithLogMethods.prototype.warn = function() {
var args = ['warn'].concat(Array.prototype.slice.call(arguments));
return this.debugLog.apply(this,args);
};
MyGlobalClassWithLogMethods.prototype.error = function() {
var args = ['error'].concat(Array.prototype.slice.call(arguments));
return this.debugLog.apply(this,args);
};
//not necessary, but it is used in my example code, so defining it
MyGlobalClassWithLogMethods.prototype.toString = function() {
return "app: " + JSON.stringify(this);
};
Next, we put those methods to use like so:
//JS line done as early as possible so rest of app can use logging mechanism
window.app = new MyGlobalClassWithLogMethods();
//only way to get "line info" reliably as well as log the msg for actual page display;
// ugly, but works. Any number of params accepted, and any kind of var will get
// converted to str using .toString() method.
console.log.apply(console,app.log('the log msg'));
console.debug.apply(console,app.debug('the log msg','(debug)', app));
console.info.apply(console,app.info('the log msg','(info)'));
console.warn.apply(console,app.warn('the log msg','(warn)'));
console.error.apply(console,app.error('the log msg','(error)'));
Now the console gets log messages with their appropriate line information as well as our app contains an array of log messages that can be put to use. For example, to display your in-app log using HTML, JQuery and some CSS the following simplistic example can be used.
First, the HTML:
<div id="debug_area">
<h4 class="text-center">Debug Log</h4>
<ul id="log_list">
<!-- console log/debug/info/warn/error ('msg') lines will go here -->
</ul>
</div>
some CSS:
.log_level_log {
color: black;
background-color: white;
font-size: x-small;
}
.log_level_debug {
color: #060;
background-color: #80FF80;
font-size: x-small;
}
.log_level_info {
color: #00F;
background-color: #BEF;
font-size: x-small;
}
.log_level_warn {
color: #E65C00;
background-color: #FB8;
font-size: x-small;
}
.log_level_error {
color: #F00;
background-color: #FBB;
font-size: x-small;
}
and some JQuery:
var theLog = app.mLog || [];
if (theLog.length>0) {
var theLogList = $('#log_list');
theLogList.empty();
for (var i=0; i<theLog.length; i++) {
theLogList.prepend($('<li class="log_level_'+theLog[i].level+'"></li>').text(theLog[i].msg));
}
}
This is a simplistic use, but once you have the mechanism in place, you can do whatever your imagination can come up with, including leaving the log lines in the code, but setting a threshold so that only warnings and errors get through. Hopefully this helps others with their projects.