Open adamschwartz opened 11 years ago
We definitely want to add line numbers. However, unfortunately, the nature of wrapping console.log
means we'll lose the ability to display the line number on the right.
There are a number of possible solutions we are considering to address this. For example, if we change the exports at the bottom of the script to something like the following:
window.log = console.log.bind(console)
window.log.format = stringToArgs
Then you could call the following and still get line numbers:
log(log.format('this is _bold_'))
If you didn't want the text to be formatted, you could still call:
log('this is _just some text with two underscores around it_')
Of course, having to wrap your string in a log.format
is certainly less sexy than we'd like. So we're considering other possible solutions as well.
On a related note, there may be some potential changes coming to console.log
. We're actively following and participating in the discussions here:
https://code.google.com/p/chromium/issues/detail?id=167911 https://bugs.webkit.org/show_bug.cgi?id=20141
Hi Adam,
I came up with a simple hack to enable logging line numbers. I have only tested it in Chrome though. Here's how it works:
log.js:19
was useless information. I got rid of it by calling toString()
on log
and assigning to window.log
using eval
.console.groupCollapsed
instead of console.log
. Clicking it opens a log statement with a link to actual file and line number, clicking which takes you to that file in the Sources tab. It only works if such a statement is logged directly using console.log
without any other parameters or styles, which is why console.group
was needed.console.group
makes all your text bold, so I had to use hacks to add font-weight: normal
everywhere.log.l
log actual line numbers, I changed it to _log = console.log.bind(console)
.I could've also added two console.log
statements: one for logging, the other for the file name and line number, but I thought that would be obtrusive and figured using console.group
would be a much elegant solution.
Limitations:
See source here: https://github.com/fleon/log/blob/master/log.coffee jsFiddle: http://jsfiddle.net/fleon/b6etu/1/
This is fantastic work. Very clever.
However, before merging I'd like to take the following steps.
console.groupCollapsed
. If all else fails we can use another userAgent
test.log
, log.l
, and log.e
perhaps).eval
to remove the line number was very clever. I'm not so sure there aren't other clever tricks like that out there waiting to be found.Thanks for your contribution!
I managed to get it working in Firefox+Firebug as well, but the hack is very ugly. It works without console.group
though.
Each log statement now shows up the filename and actual line number overlayed on top of the log.js line number (thanks to Firebug allowing position:absolute
in log styles). It's not clickable though, so I logged arguments.callee.caller
to its left, clicking which will take you to the function definition (close enough). To make sure it is positioned correctly with correct padding, I did some DOM insertion hacks (which would sorta make it slower, but we can get around that). Two console.log
s added an additional hr, which I managed to hide by overlaying with a white 1px high, 100% wide absolute box.
Nevertheless, this was a lot of fun!
Source: https://github.com/fleon/log/commit/0713275eae0f2ccfcd7f963016c4febd0e659cb7 (warning: ugly code) jsFiddle: http://jsfiddle.net/fleon/b6etu/1/
Another option, although not as independent, is to combine log.js with stacktrace.js. Here's the modified _log
function from log.js source (this is also only tested in Chrome and only with one simple test case, but we could test further if you want to go down this road):
_log = function() {
if (typeof window.printStackTrace === 'function') {
var trace = printStackTrace();
var callerLine = trace[trace.length-1];
var index = callerLine.indexOf("at ");
var clean = callerLine.slice(index+2, callerLine.length);
}
var array = makeArray(arguments);
if (clean) { array.push(clean); }
return console.log.apply(console, array);
};
Assuming you have included stacktrace.js
in your page and you call log('hello')
from line 4 of script.js
, the output will be: hello path/to/script.js:4:1
. If you don't have stacktrace.js
, everything still works fine -- just without the correct line number displayed.
See my fork at https://github.com/6twenty/log/commit/249864da2a39d80f7abd4774a11d8858a40af37c for a working example (coffeescript version updated too, but with a typo which is fixed in https://github.com/6twenty/log/commit/5f0f16820eb35c060e42dbf41a6ef8db4a5266d6).
you could do something like
if (Function.prototype.bind) {
//Preserves line numbers
window.log = Function.prototype.bind.call(console.log, console);
} else {
//Fallback
}
window.md = function(){
var args = Array.prototype.slice.call(arguments);
//style markdown in args
return args;
}
log(md("This is *italic*"));
or this:
function log(){
var args = Array.prototype.slice.call(arguments);
//style markdown in args
return Function.prototype.apply.bind(window.console.log,window.console, args)
}
log("This is *italic*")();
which would output nothing if you missed of the trailing ()
but is very concise otherwise.
@SamHasler Thanks! Those are both very interesting options.
The log(md("This is *italic*"));
is great as it's very clear what it's doing (assuming md
is understood). However, I'm not excited about adding another global to the scope. There's already a log.l
which attempts to serve this purpose, so perhaps the syntax would be log.l(log.md("This is *italic*));
. Not as good as yours but may be a good compromise. Then the library would say "If you care about line numbers, use log.l log.md
, and if you don't, just use log
".
The other approach is very tempting, but I think it's a little too tricky for our average user. I would worry too many people would miss the subtlety of the extra ()
and be frustrated with the library. Ironically, this could be mitigated with a console.log
message if the user tried log("This is *italic*")
but unfortunately we A) can't know what happens later in the call chain and B) wouldn't want to log anything additional in a log library ;). Nevertheless a similar option as above could be taken of making a log.something
which does this.
One of these will likely get us there though, so thanks again!
The user can turn on Chrome Dev Tools Settings > General > Sources > Skip stepping through sources with particular names
, and set pattern
to match log.min.js. It's worth documenting in the Readme.
However it doesn't help if they concatenate log.min.js into thier own code. See also: jsbin/jsbin#1833
Thanks @SamHasler. Didn’t know about that setting. :+1:
@SamHasler thanks for the tips with md()
I have question
When i code
log(md('[c="color: #32c5d2"] Mytexte in color : [c]'));
The console write a line in a array like this
how we can remove the bracket and first " ?
Possibly do something like this: https://github.com/eriwen/javascript-stacktrace
Or like this:
__LINE__ = (new Error).stack.split("\n")[1].match(/:([0-9]+):/)[1]
https://news.ycombinator.com/item?id=5540763See https://news.ycombinator.com/item?id=5540716 for more information.