[Javascript] creating a better console log
rene7705
rene7705 at gmail.com
Mon May 13 23:01:43 CDT 2013
update:
- freezing fixed
- setTimeout() and setInterval() gap solved <grin>
- plugged in file:line:column details via stacktracejs.com
yet to solve:
- crossing event handlers (although i'm probably going to go with each DOM
event creating a new userAction and thus a new stacktrace in
tracer.traced[userActionIdx])
- crossing callbacks from jQuery (which is going to be a bitch, I recon,
but I'll ask on the jQuery forums).
- fix the indentCount jumping around (bug?)
i'll take a nap to think the jQuery problem over, after posting this on
their forums as well of course...
latest code:
String.prototype.times = function(count) {
return count < 1 ? '' : new Array(count + 1).join(this);
}
// Enable the passage of the 'this' object through the JavaScript timers
// thanks to
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#Callback_arguments
var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval;
window.setTimeout = function (vCallback, nDelay /*, argumentToPass1,
argumentToPass2, etc. */) {
var
oThis = this,
aArgs = Array.prototype.slice.call(arguments, 2),
ua = tracer.findUA(arguments);
if (ua) aArgs.ua = ua;
return __nativeST__(vCallback instanceof Function ? function () {
vCallback.apply(oThis, aArgs);
} : vCallback, nDelay);
};
window.setInterval = function (vCallback, nDelay /*, argumentToPass1,
argumentToPass2, etc. */) {
var
oThis = this,
aArgs = Array.prototype.slice.call(arguments, 2),
ua = tracer.findUA(arguments);
if (ua) aArgs.ua = ua;
return __nativeSI__(vCallback instanceof Function ? function () {
vCallback.apply(oThis, aArgs);
} : vCallback, nDelay);
};
var tracer = {
/* object last modified : 14 May 2013, 05:53 CEST
original code by
http://javascriptweblog.wordpress.com/2010/06/01/a-tracer-utility-in-2kb/
modified by rene7705 at gmail.com with (among other things):
(1) http://stackoverflow.com/a/15582432/2379929
augmented by rene7705 at gmail with:
http://stacktracejs.com/
this code is now used in and offered as part of the web-framework at
http://fancywebapps.com
(component name : hipLog, to be released later)
problems remaining:
{1} crossing event handlers (although i'm probably going to go with each
DOM event creating a new userAction and thus a new stacktrace in
tracer.traced[userActionIdx])
{2} crossing callbacks from jQuery (which is going to be a bitch, I recon,
but I'll ask on the jQuery forums).
{3} fix the indentCount jumping around (bug?)
*/
nativeCodeEx: /\[native code\]/,
tracing: [],
traced : [],
userActions : [],
findUA : function (arg) {
var p = arg;
if (p.ua) return p.ua;
var callee = arg.callee;
var caller = callee.caller;
var stack = [callee];
while (caller) {
if (stack.indexOf(caller) < 0) {
stack.push(caller);
args = caller.arguments;
callee = args.callee;
caller = callee.caller;
} else break;
}
while (p = stack.shift()) {
if (p.arguments && p.arguments.ua) return p.arguments.ua;
};
return false;
},
traceMe: function(func, methodName, path) {
var traceOn = function() {
var
ua = tracer.findUA(arguments),
startTime = +new Date;
if (!ua) {
var
uaIdx = tracer.userActions.length,
ua = tracer.userActions[uaIdx] = {
uaIdx : uaIdx,
startTime : startTime,
path : path,
stackLevel : 0
};
tracer.traced[uaIdx] = [];
} else {
var uaIdx = ua.uaIdx;
ua.stackLevel += 1;
}
arguments.ua = ua;
var idx = tracer.traced[uaIdx].length;
tracer.traced[uaIdx][idx] = {
path : path,
arguments : arguments
};
var result = func.apply(this, arguments);
tracer.traced[uaIdx][idx].stacktrace = printStackTrace()
tracer.traced[uaIdx][idx].result = result;
tracer.traced[uaIdx][idx].timed = new Date - startTime;
tracer.traced[uaIdx][idx].stackLevel = ua.stackLevel;
return result;
};
traceOn.traceOff = func;
for (var prop in func) {
traceOn[prop] = func[prop];
}
//console.log("tracing " + path);
return traceOn;
},
traceAll: function(root, path, recurse) {
if ((root == window) || !((typeof root == 'object') || (typeof root ==
'function'))) {return;}
for (var key in root) {
if ((root.hasOwnProperty(key)) && (root[key] != root)) {
var thisObj = root[key];
if (typeof thisObj == 'function') {
if ((this != root) && !thisObj.traceOff &&
!this.nativeCodeEx.test(thisObj)) {
root[key] = this.traceMe(root[key], key,
path+'.'+key);
this.tracing.push({obj:root,methodName:key,
path:path+'.'+key});
}
}
recurse && this.traceAll(thisObj, path+'.'+key, true);
}
}
},
untraceAll: function() {
for (var i=0; i<this.tracing.length; ++i) {
var thisTracing = this.tracing[i];
thisTracing.obj[thisTracing.methodName] =
thisTracing.obj[thisTracing.methodName].traceOff;
}
//console.log("tracing disabled");
tracer.tracing = [];
}
}
the printStackTrace() function (provides file:line:column info) comes from
stacktracejs.com (free)
On Mon, May 13, 2013 at 7:59 PM, rene7705 <rene7705 at gmail.com> wrote:
> i have another problem related to the previous one;
>
> in the javascript framework that I wrote (http://fancywebapps.com), it's
> entirely possible to have multiple user clicks and background animations
> being processed at the same time.
>
> the original tracer object could not handle this, so I built an
> improvement, one that unfortunately freezes the browser for reasons I don't
> understand yet. A page with my framework where you can find the thing
> freezing the browser is up at http://freegemini.me/sites/fancywebapps.com
>
> I would greatly appreciate any tips you have to offer.
>
> Here's the new code:
>
> String.prototype.times = function(count) {
> return count < 1 ? '' : new Array(count + 1).join(this);
> }
>
> var tracer = {
> nativeCodeEx: /\[native code\]/,
> indentCount: -4,
> tracing: [],
> traced : [],
> userActions : [],
> findUA : function (arg) {
> var p = arg;
> while (p) {
> if (p.ua) return p.ua;
> if (p.arguments && p.arguments.ua) return p.arguments.ua;
> if (typeof p.callee=='function') {
> p = p.callee;
> } else if (typeof p.caller=='function') {
> p = p.caller;
> } else return false;
> }
> },
>
> traceMe: function(func, methodName, path) {
> var userAction;
> var traceOn = function() {
> var startTime = +new Date;
> var indentString = " ".times(tracer.indentCount += 4);
> debugger;
> var ua = tracer.findUA(arguments);
> if (!ua) {
> var uaIdx = tracer.userActions.length;
> ua = tracer.userActions[uaIdx] = {
> uaIdx : uaIdx,
> startTime : startTime,
> path : path
> }
> tracer.traced[uaIdx] = [];
> arguments.ua = ua;
> } else {
> var uaIdx = ua.uaIdx;
> }
> var idx = tracer.traced[uaIdx].length;
> tracer.traced[uaIdx][idx] = {
> path : path,
> arguments : arguments
> };
> console.info(indentString + path + '(' +
> Array.prototype.slice.call(arguments).join(', ') + ')');
> var result = func.apply(this, arguments);
> tracer.traced[uaIdx][idx].result = result;
> tracer.traced[uaIdx][idx].timed = new Date - startTime;
> tracer.traced[uaIdx][idx].indentCount = tracer.indentCount;
>
> console.info(indentString + path , '-> ', result, "(", new Date -
> startTime, 'ms', ")");
> tracer.indentCount -= 4;
> return result;
> };
> traceOn.traceOff = func;
> for (var prop in func) {
> traceOn[prop] = func[prop];
> }
> //console.log("tracing " + path);
> return traceOn;
> },
>
> traceAll: function(root, path, recurse) {
> if ((root == window) || !((typeof root == 'object') || (typeof root ==
> 'function'))) {return;}
> for (var key in root) {
> if ((root.hasOwnProperty(key)) && (root[key] != root)) {
> var thisObj = root[key];
> if (typeof thisObj == 'function') {
> if ((this != root) && !thisObj.traceOff &&
> !this.nativeCodeEx.test(thisObj)) {
> root[key] = this.traceMe(root[key], key,
> path+'.'+key);
> this.tracing.push({obj:root,methodName:key,
> path:path+'.'+key});
> }
> }
> recurse && this.traceAll(thisObj, path+'.'+key, true);
> }
> }
> },
>
> untraceAll: function() {
> for (var i=0; i<this.tracing.length; ++i) {
> var thisTracing = this.tracing[i];
> thisTracing.obj[thisTracing.methodName] =
> thisTracing.obj[thisTracing.methodName].traceOff;
> }
> console.log("tracing disabled");
> tracer.tracing = [];
> }
> }
>
> note: the indentCount variable isn't handled correctly yet. needs to be
> moved into the ua object.
>
>
> On Mon, May 13, 2013 at 5:23 AM, rene7705 <rene7705 at gmail.com> wrote:
>
>> Hi.
>>
>> I would like to create a better console log, one in which you can see per
>> user action what your javascript program does.
>>
>> I've found some source code somewhere on the net that allows you to log
>> all function calls;
>>
>> String.prototype.times = function(count) {
>> return count < 1 ? '' : new Array(count + 1).join(this);
>> }
>>
>> var tracer = {
>> nativeCodeEx: /\[native code\]/,
>> indentCount: -4,
>> tracing: [],
>>
>> traceMe: function(func, methodName, path) {
>> var traceOn = function() {
>> var startTime = +new Date;
>> var indentString = " ".times(tracer.indentCount += 4);
>> console.info(indentString + path + '(' +
>> Array.prototype.slice.call(arguments).join(', ') + ')');
>> var result = func.apply(this, arguments);
>> console.info(indentString + path , '-> ', result, "(",
>> new Date - startTime, 'ms', ")");
>> tracer.indentCount -= 4;
>> return result;
>> }
>> traceOn.traceOff = func;
>> for (var prop in func) {
>> traceOn[prop] = func[prop];
>> }
>> console.log("tracing " + methodName);
>> return traceOn;
>> },
>>
>> traceAll: function(root, path, recurse) {
>> if ((root == window) || !((typeof root == 'object') || (typeof root ==
>> 'function'))) {return;}
>> for (var key in root) {
>> if ((root.hasOwnProperty(key)) && (root[key] != root)) {
>> var thisObj = root[key];
>> if (typeof thisObj == 'function') {
>> if ((this != root) && !thisObj.traceOff &&
>> !this.nativeCodeEx.test(thisObj)) {
>> root[key] = this.traceMe(root[key], key,
>> path+'.'+key);
>> this.tracing.push({obj:root,methodName:key,
>> path:path+'.'+key});
>> }
>> }
>> recurse && this.traceAll(thisObj, path+'.'+key, true);
>> }
>> }
>> },
>>
>> untraceAll: function() {
>> for (var i=0; i<this.tracing.length; ++i) {
>> var thisTracing = this.tracing[i];
>> thisTracing.obj[thisTracing.methodName] =
>> thisTracing.obj[thisTracing.methodName].traceOff;
>> }
>> console.log("tracing disabled");
>> tracer.tracing = [];
>> }
>> }
>> tracer.traceAll (myObject, 'myObject', true);
>>
>>
>> However, this does not track anonymous functions defined inside functions
>> (possibly as callbacks listed inside some object)...
>> I was wondering if anyone here knows of a way to track those anonymous
>> functions as well.
>>
>> I plan to build up some kind of array instead of log to the console.infodirectly, and display the results in a tree view or whatever is better than
>> a treeview.
>>
>> This component could have a lot of potential.. For instance, it could be
>> used to record user interaction on the website, and in case of an error
>> transmit what happened back to the server to be logged and displayed with
>> details to the developer later on.
>>
>> I'm also wondering about what would be the best way to exclude functions from
>> the log/view that are called very often (as part of an animation loop) but
>> often without doing anything (a scrollpane that doesn't need resizing at
>> that moment, for instance)
>>
>>
>>
>
More information about the Javascript
mailing list