AngularJs has an impressive and robust logging mechanism through the $logService
and $log
injection. However, Angular logs everything to the console
, which is neither a robust or scalable solution. Sometimes, you need to be able to intercept the exceptions and do something extra. This could be as simple as adding extra information or sending all logs to the server/database. Below I've included two different ways that you can achieve that.
Option 1
The first one is pretty simple and allows you to hook into the $exceptionHandler
and pass a logger in the form of an AngularJs factory. The factory contains only one method => log()
. This method first calls the base $log.error()
method and after that point we have all the data we need to do as we please. The only limitation is that this custom logger deals only with errors and exceptions. I've attached the sample code below:
You can also find a working example in Plunker
Option 2
The second logger implementation is much more powerful. In this case we use a neat AngularJs feature, decorators, to intercept all logging calls and then enhance them by adding our custom code. Decorators are great and particularly powerful but not as well advertised as other features in AngularJs. They definitely have power and can help you solve lots of problems. The code below consists of 2 parts:
- An Decorator
- A Factory
The Decorator is where we intercept and enhance the AngularJs logger. The factory is where we implement all the custom logic. In the factory you can send messages to a queue, call a 3rd party API (NewRelic) or "phone home" to the server and persist your logs to the database. The really cool feature about this solution is that we get access to all the logging events that are already built in AngularJs. By calling, for example, $log.info('some message');
you get both the built-in functionality which outputs to the console and the custom functionality you defined in your factory.
Again, there is a working example in Plunker.
What logging strategies are you using with your solution? Do you feel there's a better way to implement this? Let me know in the comments