Logging in Angular apps ... and how to filter those log messages
The classic way to log in JavaScript is through the delightful console.log
call; it's pretty brute-force - it logs. That's it. No filtering log messages, no log levels (i.e. warn, error, etc.).
What's nice is that Angular provides us a handy service that wraps console.log
and it's called, funnily enough, $log
.
$log
is a simple service that, when included in your code, provides four methods:
-
error
: for, well, errors - also gives you a stack trace -
info
: for informational messages -
log
: uh, log messages? -
warn
: warning messages, duh
2 of those are pretty obvious as to their function: warn
& error
. How you use info
and log
are really up to you; to be, they're pretty similar. I typically use log
to mean debug. Info would be for generalised informational messages (such as a service saying "Hey, I'm using the staging server")
Obtaining the Angular $log
is pretty simple, just declare it as a dependency in your particular 'thing', so for a controller:
function SomeCtrl($scope, $log) {
$log.info('SomeCtrl - starting up, yeah!');
}
Filtering those $log
messages
Saying all of that, getting a lot of log in the console can be a little like receiving a ton of spam. Plus, maybe you don't want to log everything. Maybe you want to send errors to a remote server.
So, Angular provides us with the concept of 'decorators' and these allow us to wrap the original $log
service and provide our own implementations (or wrap the original ones).
The following example (borrowed from this Google Group thread) is silent when it comes to log
messages (because, for me, they're debug messages) and decides to call alert()
for any error
messages.
myApp.config(function($provide) {
$provide.decorator('$log', function($delegate, $sniffer) {
var _log = $delegate.log; //Saving the original behavior
$delegate.log = function(message) { };
$delegate.error = function(message) {
alert(msg);
}
return $delegate;
});
})
A little more info on $log
can be found on the Angular documentation page here.
Written by Oliver Tupman
Related protips
6 Responses
it would be nice if the $log service could be configured on an module / entity (controller, directive, factory, ...) level too, as all Java logging frameworks support
One of the things I love about Angular.js is how I keep learning formal computer science terms using it. 'Decorators' - nice.
@andywoodly check out http://www.webdeveasy.com/service-providers-in-angularjs-and-logger-implementation/
@andywoodly - if I understand you correctly, you can completely override the behaviour by completely overriding the service returned when the $log is injected. This can be done by simply defining your own service called '$log'. As simple as that. The catch however is that Angular itself uses the $log service internally to emit logs. so ensure that whatever you do, you maintain the default interface, i.e., provide the 4 default methods $log.log(), $log.info(), $log.warn(), $log.error(). Even if as empty stubs.
bPratik.in
Actually the console API has .log, .warn, .error and other methods, not just .log.
In fact it has .assert, .count and other useful methods. See https://developer.chrome.com/devtools/docs/console-api
Angular, (as of 1.1?) has $log.debug
as well. So once again, I'm at a loss as to where to use .log()
vs .info()