Reputation: 4668
When I use angular $log service, all the lines in the console show up with a reference to angular.js:5687 instead of the line where I called the $log.log function.
How can I get a reference to the line where I called $log? Also I have my own service that wraps around $log, how can I reference calls to my service instead of $log?
For example in Logger.js:
1) angular.module('MyApp').factory('Logger', function($log){
2) return { log : function(msg) { $log.log(msg); };
3) });
And in SomeCtrl.js
1) angular.module('MyApp').controller('SomeCtrl', function($scope, $log, Logger) {
...
10) $log.log('Hi from $log'); // reference to SomeCtrl.js:10
...
25) Logger.log('Hi from Logger'); // reference to SomeCtrl.js:25
Upvotes: 2
Views: 1487
Reputation: 4668
Credit to @Langdon for pointing me in the right direction.
[NOTE] this solution will only work in Chrome. For more info look at:
Here is the workaround I implemented:
Object.defineProperty(window, '__stack', {
get : function() {
var orig = Error.prepareStackTrace;
Error.prepareStackTrace = function(_, stack) {
return stack;
};
var err = new Error;
Error.captureStackTrace(err, arguments.callee);
var stack = err.stack;
Error.prepareStackTrace = orig;
return stack;
}
});
Logger.log = function(msg) {
var stack = __stack;
var link = stack[1].getFileName() + ':' + stack[1].getLineNumber();
console.groupCollapsed("%c" + msg, "font-weight: normal;");
$log.log(link); // or console.log(link) if you're not using angular.
console.groupEnd();
};
[NOTE] In the chrome dev tools console I do not know how to overwrite the link that is given on the right. I have looked for documentation about that but I didn't find anything. Please let me if you know if you find out as this would look much neater.
Upvotes: 1
Reputation: 20073
Since I assume you're logging only in development and, like most developers, you're developing in Chrome, you can add a property to the global scope like so:
via Accessing line number in V8 JavaScript (Chrome & Node.js)
Object.defineProperty(window, '__stack', {
get: function(){
var orig = Error.prepareStackTrace;
Error.prepareStackTrace = function(_, stack){ return stack; };
var err = new Error;
Error.captureStackTrace(err, arguments.callee);
var stack = err.stack;
Error.prepareStackTrace = orig;
return stack;
}
});
Object.defineProperty(window, '__line', {
get: function(){
return __stack[1].getLineNumber();
}
});
console.log(__line);
And now you can use __line
anywhere in your code.
Edit: It doesn't look like you can get the filename from the call stack. If you're writing clean JavaScript, each file should have its own scope in which you could define var filename = 'test.js';
, so your could look like:
Defined globally somewhere:
Object.defineProperty(window, '__prevLine', {
get: function () {
console.log('__line', __stack);
return __stack[2].getLineNumber();
}
});
function log(s) {
console.log(s, __prevLine)
}
And your implementation:
(function () {
var _scriptName = 'test.js';
// ... lots of code
log('something happened', _scriptName);
}());
Here's a fiddle that demonstrates the idea:
http://jsfiddle.net/langdonx/zJJ8r/
Upvotes: 1