I did an example in my AzureDNS App today of how to add a ApiController that will log client side error to a server side store.
Coming from a C# background I am used to having a central logging store (e.g. SQL table or SEQ more recently) that all errors are dumped too. When running code on a server its easy for an app to throw its logs into something that is behind the firewall and catalogs the logs from all your apps nicely.
When you have code that is running in someone’s web browser that not always as easy, but what I’ve done with this example is just create a controller on /api/Log/Error within the running app that i can throw my JavaScript Exceptions at, then add a call from Angular’s global exception handler.
The Log Controller can be found here
The log error method is pretty straight forward, the logger object is passed in via DI from autofac
[Route("~/api/Log/Error")] [HttpPost] // POST: api/Log/Error public void PostError([FromBody]string value) { _logger.Error(value); }
The the global error handler in Angular is done as follows
'use strict'; angular.module('AzureDNSUI') // This would be changed to your app name if reusing this code .factory('$exceptionHandler', function($injector) { return function(exception, cause) { var $http = $injector.get("$http"); var $log = $injector.get("$log"); exception.message += ' (caused by "' + cause + '")'; $log.log(exception); // Logs to console $http.post('/api/Log/Error', JSON.stringify(exception)); // Where the magic happens throw exception; }; });
An example error from Angular in our SEQ server below:
There is a few fields that we can customize that I do by default from the Serilog config, some of these are not relevant for the javascript errors, for example the SourceContext will always be the same, I’ll do a follow-up post about collecting client information to pass through later.