Updated: now with Sidekiq integration code, thanks to purephase.
So, you’ve shipped something
Now, hopefully, users are coming to use your application, whether a brand new blog system or photo application or whatever great product you created. While you took great length to ensure your application quality (writing specs, testing it manually, etc.), chances are good that one of your user will at some point bump into a technical problem.
Your SMTP server will be badly configured. Your connection to one of the external service will return an error. Validation for the email in sign up form will fail. Browsing a non existing page will trigger a 404 error due to a broken link. An network outage will cause a broken connection to your postgresql database.
The problem is not that it will happen (it will). The problem is that you may never know about it (or far too late), and been left with a buggy product and a dissatisfied user (not all of them will notify you, unfortunately). Even if they stay, you’ll miss the opportunity of doing proactive support by contacting the user directly once fixed.
Now, imagine if you could know exactly which errors happen on your production, with clear information about the server and the request that triggered them.
Errbit is an open source implementation of Airbrake, a well known error monitoring tool. Errbit contributors (thanks guys!) has made an API compatible version of Airbrake that you can install yourself. Errbit is (of course) implemented in Ruby (it’s a Rails app).
In a nutshell, once configured properly, Errbit gives you a view of all errors happening in your application, split by environment, and with all the request parameter linked to it - everything you need to reproduce, understand or debug it.
Look at Errbit documentation for the install - I’ll concentrate more on the app side.
To start using Errbit in your application, you need to:
Add the gem to your Gemfile & run a bundle install:
Configure it in an initializer:
Airbrake.configure do |config| config.api_key = ENV['ERRBIT_API_KEY'] config.host = ENV['ERRBIT_HOST'] config.port = 80 config.secure = config.port == 443 config.environment_name = Rails.env.production? ? `hostname` : Rails.env end
Note the `hostname` that allows us to get a different environment name for our staging & production (even if both are “production” environment in Rails terms). As usual, the API keys or other secret are in environment variables, as we don't want those in our source control.
Airbrake will be called for all unrescued exception. You can also decide to call it yourself, even if you do rescue an exception, to add your custom handling:
class ApplicationController < ActionController::Base rescue_from APIError: :render_resource_error ... def render_resource_error(exception) Airbrake.notify(exception, airbrake_request_data) flash[:error] = exception.message redirect_to root_path end end
This code will intercept all “APIError” (whatever what it can be) and route them to a method render_resource_error. There, we notify the end user (using a flash) with a nice message, redirect him to a sure url (the root), and send all the details to Errbit. airbrake_request_data is a “magical” method that Airbrake generates in all your controllers that returns useful info for Errbit to digest (see the source here).
Voila! A nice UI with all your exceptions on the Errbit server:
Now you can see all errors that happen in your application with a single click on your Errbit server bookmark - and get valuable information about them (parameter used in the request, notably). In addition, Errbit group the errors with the same message, so it is very easy to see which are “one time” and which ones come back a lot.
Update: Sidekiq integration
I shared this post on Reddit, and Redditor purephase was kind enough to enrich it with a Sidekiq integration example (Sidekiq is a well known background processor like DelayedJob or Resque). Thanks to him!
in airbrake init:
config.async do |notice| AirbrakeDeliveryWorker.perform_async(notice.to_xml) end
now create an airbrake_delivery_worker.rb:
class AirbrakeDeliveryWorker include Airbrake include Sidekiq::Worker sidekiq_options queue: :airbrake, retry: false def perform(notice) Airbrake.sender.send_to_airbrake notice end end
Now, of course, you still need to go there to get those exceptions. The good thing is that Errbit can notify you on your email each time it catches a new error. This works well, but we’ve find another solution even better for us - stay tuned.