Make console.log log current line
-
Ok JavaScript ninjas, I have this utility which basically is a wrapper around console.log:
https://github.com/Eldelshell/jobhunter-chrome-app/blob/master/js/utils/Logger.js
It works, but of course, all lines in the console are Logger.js:23
So, how can I make the call to console.log show the correct file and line number?
Note 1
I know there are libraries that do this, but I want to understand what I am doing wrong.
-
yeah.... that's gotten much less fun thanks to arguments.caller being removed....
but you can do this:
function a(){ var err = new Error(); var caller_line = err.stack.split("\n")[2]; var index = caller_line.indexOf("at "); var clean = caller_line.slice(index+2, caller_line.length); console.log(clean); } function b(){ a(); } b();
tested on nodejs 4.0 and Chrome fourty mumble mumble mumble
-
Your code's buggy.
Well maybe not in Node or whatever, it's broken in browsers.
You can't assume that a "console" object exists.
-
We ran into that issue just a few weeks ago -- someone accidentally left a console.log in, and IE wouldn't render the page.
-
I've seen that a million times. Lazy JS developers developing based on "what Chrome does" instead of reading the specs.
Your shit looks to be specific to Chrome anyway, so maybe it doesn't matter. But. Any chance to educate people on "console is not guaranteed to exist, guyz!" and I'll take it.
-
Your shit looks to be specific to Chrome anyway, so maybe it doesn't matter.
Well, it's a Chrome application, so yes, it's specific to Chrome. Also, the reason I always wrap console is exactly because of stupid IE.
-
Your code's buggy.
fine....
//polyfill console.log (function(global) { 'use strict'; global.console = global.console || {}; var con = global.console; var prop, method; var empty = {}; var dummy = function() {}; var properties = 'memory'.split(','); var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' + 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(','); while (prop = properties.pop()) if (!con[prop]) con[prop] = empty; while (method = methods.pop()) if (typeof con[method] !== 'function') con[method] = dummy; })(typeof window === 'undefined' ? this : window); //actually do the thing function a(){ //this is probably wrong for some browser. only rely on it for debugging at the best. var err = new Error(); var caller_line = err.stack.split("\n")[2]; var index = caller_line.indexOf("at "); var clean = caller_line.slice(index+2, caller_line.length); console.log(clean); } function b(){ a(); } b();
-
Also, the reason I always wrap console is
But but... in the code you linked us to, you didn-- oh never mind, fuck it.
-
function a(){
//this is probably wrong for some browser. only rely on it for debugging at the best.
var err = new Error();
var caller_line = err.stack.split("\n")[2];
var index = caller_line.indexOf("at ");
var clean = caller_line.slice(index+2, caller_line.length);
console.log(clean);
}That doesn't work. I get this:
Object.__log (http://localhost:8000/js/utils/Logger.js:23:13)
-
hmm.... play with the index on the err.stack.split line.
try
4
as the value maybe?
-
Yeah, debugged the Error object and the line is there, but this doesn't fix the real issue I wanted to fix:
-
oh. that. yeah that you can't fix that.
-
Ooo, I was confused too.
Yeah, you don't control that at all. The only way to get the line number to appear correctly there is to not centralize your logging.
-
oh. that. yeah that you can't fix that.
Yeah, you don't control that at all. The only way to get the line number to appear correctly there is to not centralize your logging.
Your JavaScript abilities are not that of a true Ninja. Of course it can be done:
-
Seems like the magic happens here:
-
hmm........ thats..... interesting.....
-
Hax
-
-
It's only supported in every major browser.
-
It's only supported in every major browser.
If you ignore the big red box at the very top of the page that says "This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future."
-
The trick is that when it works it's actually calling
console[methodName]
. You can make it work too, as it is effectively:define('magic/console', function() { function noop() {} var c = typeof console !== 'undefined' ? console : {}; return { trace: c.trace && c.trace.bind(c) || noop, log: c.log && c.log.bind(c) || noop, debug: c.debug && c.debug.bind(c) || noop, info: c.info && c.info.bind(c) || noop, warn: c.warn && c.warn.bind(c) || noop, error: c.error && c.error.bind(c) || noop }; });
That's what they are doing here:
and here
So they proxy the console's own methods onto the
Logger
object, which is how you get the nice correct line numbers (because the browser is doing it for you).You can make the whole binding part even simpler if you just want access to the console if it exists. Just return the real console object:
if (console && console.log && other.tests.here) return console;