Hire Us

Asynchronous Airbrake delivery – avoiding latency in application response time

TL;DR

Update airbrake-gem to last version and enable asynchronous delivery option to avoid latency in application response time.

Introduction

We used Airbrake (ex-Hoptoad) to track errors in our application. But, several months ago we noticed delays in application response time, caused by Airbrake error reporting.In some cases delay got up to 5 seconds and it wasn’t good. Any frequently-reproduced bug could easily block the whole application server.

Asynchronous to the rescue

Main issue is in how the whole reporting works. If application throws an exception, Airbrake-notifier catches it and issues HTTP-request to the API-collector service. This time can be about ~200-300ms, which is ok for HTTP-request, but isn’t very good for response time of application.To fix it, instead of sending notification synchronously, it should be put in some queue and sent later via special worker. This worker can be thread, actor or even Resque/Sidekiq-like solution.At that moment, Airbake dev-team already implemented hard-coded solution based on GirlFriday gem. All you need, is to set config.async = true, and all notifications are put into GirlFriday-queue. GirlFriday-worker fetches notification from queue in separate thread without affecting application response time.It is cool, but we use JRuby and Akka. Akka provides us with the same functionality as GirlFriday and we didn’t want to duplicate our dependencies. Instead we came up with a patch for airbrake which adds ability to setup custom asynchronous handler.Now you can use Resque/Sidekiq or even bare Thread.new. Even more, MRI 1.8.x isn’t supported by GirlFriday, so default case isn’t suitable for it. But Thread.new or Resque can be easily applied for this case.

Configuration

If you don’t use any actor-based solution(e.g. Celluloid, Akka) and your Ruby is MRI 1.9+, Rubinius 2.0+, or JRuby 1.6+ just enable async-mode and it should work:
Airbrake.configure do |config|
  # ...
  config.async = true
end
For Ruby 1.8.x use Thread.new edition:
Airbrake.configure do |config|
  # ...
  config.async do |notice|
    Thread.new { Airbrake.sender.send_to_airbrake(notice) }
  end
end
or rewrite it to match your actor/queue-based solution.To get more info, read Airbrake wiki page with different configurations. Examples include custom configuration for Resque and Sidekiq workers.

Summary

It’s great that now Airbrake supports asynchronous error-reporting. Enable it and your application will be protected from random delays caused by slow response time from Airbrake collector service.