Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The problem with wrapping console.log is that you lose the ability to know what line number initiated the log entry. The line number Chrome gives for the log line will always be where you call console.log inside the wrapper, not the line where you call the wrapper. Since there's no way to grab the line number of a caller in JS (Chrome's dev console uses browser hooks unavailable in JS), you can't even emulate the line number reporting yourself as a suffix to the log entry.


Here is a way to fix this: https://gist.github.com/bgrins/5108712. When you call `log` it will preserve the line number.

Here is a demo: http://jsfiddle.net/bgrins/MZWtG/.


Beautiful solution -- line number links work and everything. You've just made my day.


This is brilliant!


Using straight console.log statements seems to be non-negotiable for effective debugging, at least until a good workaround for the above is found.

For using Chrome's logging styles, we define a few short helper functions — l1(), l2(), l3(), etc. — that return predefined CSS strings, then doing our logging like

    console.log("%cThis is a heading", l1())
    console.log("%cLess important stuff", l2())
This means you're only adding 6 or so characters to get nice styled console messages that also maintain the nice line numbers and links to the source. Plus, it's similar enough to h1, h2, etc. that it's easy to remember.

We found that varying the font color (black vs. gray) and margin-left (2em, 4em) were most helpful in differentiating more and less important log messages.


I recommend simply using console.debug, console.log, console.warn, and console.error, which differentiate for you.


What about `console.info()`? Or is it a bit too adventurous?


info and log are indistinguishable, at least in Chrome.


Yes. So much about differentiation.


Maybe add console.assert to that list:

    console.assert(str.length === 10, "String is not 10 characters long!");
and console.group/groupEnd

    console.group("sums");
    console.log(1 + 1);
    console.log(2 - 3);
    console.groupEnd();


You actually can get the line number of a caller in JS: https://github.com/eriwen/javascript-stacktrace


You can just parse (new Error).stack:

    var __LINE__ = (new Error).stack.split("\n")[1].match(/:([0-9]+):/)[1];


I do something similar for logging my node apps... in .Net I use reflection for essentially the same.


`(new Error()).stack` is non-standard. But that’s a nice hack, nevertheless.


The underlying construct (console.log processing "%c" and styles) is nonstandard to begin with.


Yes. It will not break, though.

Unless you’re running it on an old IE that doesn’t host the `window.console` object.


Note: that uses arguments.callee, which is disallowed in ES5 strict-mode.


After looking at the code in more depth, I feel I should point out that it looks like `arguments.callee` is only the last-ditch fallback for generating a trace. I see baked-in support for Chrome, IE, FF, Safari, and Opera, and so unless your preferred browser is something else (or you want to target every possible browser) then you could change just a few lines to make it strict mode compliant.


Thanks for these suggestions. You can track progress on this here: https://github.com/adamschwartz/log/issues/1


This will severely degrade performance in almost every scenario. I don't recommend doing it by default, though it is a nice feature to have. Sometimes you want to be able to call console.log a few times per frame in a game without your framerate dropping into the single digits.


Calling `console.log()` in “production mode” is a bad idea, anyway.

Ideally, you’ll want those calls stripped at some point, in your build script.


I found a way... well, sort of:

    var log = function(){
        args = [].slice.call(arguments);
        args.unshift(console);
        return console.log.bind.apply(console.log, args) 
    }
But you have to add extra parenthesis at the end, hopefully is not too much overhead for most devs.

    log("message")()


> there's no way to grab the line number of a caller in JS

But this is easily fixed by converting the function call to a macro, right?

Oh wait - this isn't a ClojureScript library... so nevermind.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: