{"id":3211,"date":"2012-11-26T19:15:20","date_gmt":"2012-11-26T16:15:20","guid":{"rendered":"http:\/\/railsware.com\/blog\/?p=3211"},"modified":"2017-12-13T20:44:02","modified_gmt":"2017-12-13T17:44:02","slug":"asynchronous-airbrake-configuration","status":"publish","type":"post","link":"https:\/\/railsware.com\/blog\/asynchronous-airbrake-configuration\/","title":{"rendered":"Asynchronous Airbrake delivery &#8211; avoiding latency in application response time"},"content":{"rendered":"<style>\r\ndiv.wp-geshi-highlight-wrap5,<br \/>\r\n.wp-geshi-highlight-wrap4,<br \/>\r\n.wp-geshi-highlight-wrap3,<br \/>\r\n.wp-geshi-highlight-wrap2,<br \/>\r\n.wp-geshi-highlight-wrap,<br \/>\r\n.wp-geshi-highlight,<br \/>\r\n.ruby,<br \/>\r\npre.de1 {<br \/>\r\nbackground: #F0F0F0!important;<br \/>\r\npadding: 0!important;<br \/>\r\nmargin: 0!important;<br \/>\r\nborder: 0!important;<br \/>\r\nbox-shadow: none !important;<br \/>\r\n-moz-box-shadow: none !important;<br \/>\r\n-khtml-box-shadow: none !important;<br \/>\r\n-webkit-box-shadow: none!important;<br \/>\r\nwidth: auto !important;<br \/>\r\nborder: none!important;<br \/>\r\ndisplay: block!important;<br \/>\r\nborder-radius: 0 !important;<br \/>\r\nposition: static!important;<br \/>\r\n}<br \/>\r\npre.de1 {<br \/>\r\n  font-size: 1em !important;<br \/>\r\n  font-family: Consolas, Monaco, monospace !important;<br \/>\r\n  padding: 10px 15px !important;<br \/>\r\n}<br \/>\r\n<\/style>\r\n<h2>TL;DR<\/h2>\r\nUpdate airbrake-gem to last version and enable asynchronous delivery option to avoid latency in application response time.\r\n<h2>Introduction<\/h2>\r\nWe used <a href=\"http:\/\/airbrake.io\">Airbrake<\/a> (ex-Hoptoad) to track errors in our application. But, several months ago we noticed delays in application response time, caused by Airbrake error reporting.\r\n\r\nIn some cases delay got up to 5 seconds and it wasn&#8217;t good. Any frequently-reproduced bug could easily block the whole application server.\r\n<h2>Asynchronous to the rescue<\/h2>\r\nMain 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&#8217;t very good for response time of application.\r\n\r\nTo 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.\r\n\r\nAt that moment, Airbake dev-team already implemented hard-coded solution based on <a href=\"https:\/\/github.com\/mperham\/girl_friday\">GirlFriday gem<\/a>. All you need, is to set <em>config.async = true<\/em>,\r\nand all notifications are put into GirlFriday-queue. GirlFriday-worker fetches notification from queue in separate thread without affecting application response time.\r\n\r\nIt is cool, but we use JRuby and Akka. Akka provides us with the same functionality as GirlFriday and we didn&#8217;t want to duplicate our dependencies. Instead we <a href=\"https:\/\/github.com\/airbrake\/airbrake\/pull\/116\/files\">came up with a patch for airbrake<\/a> which adds ability to setup custom asynchronous handler.\r\n\r\nNow you can use Resque\/Sidekiq or even bare Thread.new. Even more,\r\nMRI 1.8.x isn&#8217;t supported by GirlFriday, so default case isn&#8217;t suitable for it. But Thread.new or Resque can be easily applied for this case.\r\n<h2>Configuration<\/h2>\r\nIf you don&#8217;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:\r\n<pre lang=\"ruby\">Airbrake.configure do |config|\r\n  # ...\r\n  config.async = true\r\nend\r\n<\/pre>\r\nFor Ruby 1.8.x use Thread.new edition:\r\n<pre lang=\"ruby\">Airbrake.configure do |config|\r\n  # ...\r\n  config.async do |notice|\r\n    Thread.new { Airbrake.sender.send_to_airbrake(notice) }\r\n  end\r\nend\r\n<\/pre>\r\nor rewrite it to match your actor\/queue-based solution.\r\n\r\nTo get more info, read <a href=\"https:\/\/github.com\/airbrake\/airbrake\/wiki\/Using-Airbrake-asynchronously\">Airbrake wiki page with different configurations<\/a>. Examples include custom configuration for Resque and Sidekiq\r\nworkers.\r\n<h2>Summary<\/h2>\r\nIt&#8217;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.","protected":false},"excerpt":{"rendered":"<p>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&#8230;<\/p>\n","protected":false},"author":25,"featured_media":3218,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3],"tags":[],"coauthors":["Sergii Boiko"],"class_list":["post-3211","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"aioseo_notices":[],"categories_data":[{"name":"Engineering","link":"https:\/\/railsware.com\/blog?category=development"}],"post_thumbnails":"https:\/\/railsware.com\/blog\/wp-content\/themes\/railsware\/vendors\/images\/article-thumbnail-default.jpg","amp_enabled":true,"_links":{"self":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/3211","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/comments?post=3211"}],"version-history":[{"count":23,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/3211\/revisions"}],"predecessor-version":[{"id":9239,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/3211\/revisions\/9239"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media\/3218"}],"wp:attachment":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media?parent=3211"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/categories?post=3211"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/tags?post=3211"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/coauthors?post=3211"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}