Effective error reporting with EmberJS and Bugsnag
An important part of a professional application is catching and reporting bugs. In Candidio, we report bugs from our EmberJS application to Bugsnag. Bugsnag has great documentation and a good amount of language support with their first-party notifier libraries. We're quite happy with their service and look forward to using them for the forseeable future.
Raygun recently detailed how to send error reports to their service, so I thought I'd pass along how we accomplished a similar feat with Bugsnag.
Bugsnag.js
Get Bugsnag's Javascript notifier with Bower using the command bower install --save bugsnag
. Import the bugsnag.js source into your app in Brocfile.js
with app.import('bower_components/bugsnag/src/bugsnag.js');
.
In .jshintrc
add "Bugsnag": true
to the predef
hash, so you don't get squawked at every time you use the Bugsnag
global variable.
Initializer
Create a new initializer at app/initializers/bugsnag.js
on the command line with the ember g initializer bugsnag
command. In the initialize function, we're going to declare the Bugsnag API key, the releaseStage (current environment), and the stages we want to notify Bugsnag from. In Candidio, we only send Bugsnag errors from our staging environment and the production site.
Bugsnag.apiKey = config.APP.BUGSNAG.API_KEY;
Bugsnag.releaseStage = config.environment;
Bugsnag.notifyReleaseStages = ["staging", "production"];
Routing Errors
The first type of error we want to report is routing and edge cases, which we'll catch with Ember.onerror. In this error report and the following, we're sending along the current path, rather than letting Bugsnag grabbing the URL from location.href
. I've found that in the context of EmberJS development, this is more useful.
Ember.onerror = function(error) {
Bugsnag.context = appController.get('currentPath');
Bugsnag.notifyException(error);
console.error(error.stack); // Still send the error to the console
};
Promise/AJAX Errors
We should also catch errors from rejected Promises, which we can do similarly with the RSVP.on('error') method.
Ember.RSVP.on('error', function (error) {
Bugsnag.context = appController.get('currentPath');
Bugsnag.notifyException(error);
});
Ember Logger Errors
Let's also send any errors logged by Ember's internal logger service and make sure they still get sent to the console.
Ember.Logger.error = function (message, cause, stack) {
var currentRoute = appController.get('currentPath');
Bugsnag.context = currentRoute;
Bugsnag.notifyException(new Error(message), null, { cause: cause, stack: stack });
console.error(stack);
};
Bonus: Javascript Sourcemaps
Sourcemaps are enabled by default on the ember-cli development build, but to get a sourcemap on every build, including production, add the following sourcemaps
hash in Brocfile.js
. Bugsnag will get the sourcemap declaration at the bottom of our concatenated source and give you a much improved stack track over the minified source.
// Brocfile.js
var app = new EmberApp({
...
sourcemaps: {
"enabled": true,
"extensions": ["js"]
}
});
Gist of the Bugsnag integration
Other useful details you can send to Bugsnag
- Current user data
- Meta data about the current user's session, containing entities, or account.
Updated March 18, 2015: We should still log out appropriate errors to the console. Thanks to Ben Holmes for the tip!