From 451a930f64b45c4824391e8ddeda2e853879ee5d Mon Sep 17 00:00:00 2001 From: Ray Krueger Date: Fri, 6 May 2011 16:36:41 -0500 Subject: [PATCH 1/4] Fixing/updating the hoptoad backend The previous version of the hoptoad back end no longer worked. This is due to Hoptoad changing their API somewhere along the way. I've updated the code here to simply use the hoptoad_notifier gem that folks are likely already using in their apps. This puts the maintenance and configuration responsibility into that gem rather than here in resque. --- lib/resque/failure/hoptoad.rb | 131 +++++----------------------------- 1 file changed, 16 insertions(+), 115 deletions(-) diff --git a/lib/resque/failure/hoptoad.rb b/lib/resque/failure/hoptoad.rb index 27d05874d..b1fd32c83 100644 --- a/lib/resque/failure/hoptoad.rb +++ b/lib/resque/failure/hoptoad.rb @@ -1,6 +1,4 @@ -require 'net/https' -require 'builder' -require 'uri' +require 'hoptoad_notifier' module Resque module Failure @@ -10,28 +8,17 @@ module Failure # # require 'resque/failure/hoptoad' # - # Resque::Failure::Hoptoad.configure do |config| - # config.api_key = 'blah' - # config.secure = true + # Resque::Failure::Multiple.classes = [Resque::Failure::Redis, Resque::Failure::Hoptoad] + # Resque::Failure.backend = Resque::Failure::Multiple # - # # optional proxy support - # config.proxy_host = 'x.y.z.t' - # config.proxy_port = 8080 - # - # # server env support, defaults to RAILS_ENV or RACK_ENV - # config.server_environment = "test" - # end + # Once you've configured resque to use the Hoptoad failure backend, + # you'll want to setup an initializer to configure the Hoptoad. + # + # HoptoadNotifier.configure do |config| + # config.api_key = 'your_key_here' + # end + # For more information see https://github.com/thoughtbot/hoptoad_notifier class Hoptoad < Base - # From the hoptoad plugin - INPUT_FORMAT = /^([^:]+):(\d+)(?::in `([^']+)')?$/ - - class << self - attr_accessor :secure, :api_key - attr_accessor :proxy_host, :proxy_port, :proxy_user, :proxy_pass - attr_accessor :server_environment - attr_accessor :host, :port - attr_accessor :http_read_timeout, :http_open_timeout - end def self.count # We can't get the total # of errors from Hoptoad so we fake it @@ -39,101 +26,15 @@ def self.count Stat[:failed] end - def self.configure - yield self - Resque::Failure.backend = self - end - def save - http = use_ssl? ? :https : :http - host = self.class.host || 'hoptoadapp.com' - port = self.class.port - url = URI.parse("#{http}://#{host}:#{port}/notifier_api/v2/notices/") - - request = Net::HTTP::Proxy self.class.proxy_host, self.class.proxy_port, - self.class.proxy_user, self.class.proxy_pass - http = request.new(url.host, url.port) - headers = { - 'Content-type' => 'text/xml', - 'Accept' => 'text/xml, application/xml' - } - - http.read_timeout = self.class.http_read_timeout || 5 # seconds - http.open_timeout = self.class.http_open_timeout || 2 # seconds - - http.use_ssl = use_ssl? - - begin - response = http.post(url.path, xml, headers) - rescue TimeoutError => e - log "Timeout while contacting the Hoptoad server." - end - - case response - when Net::HTTPSuccess then - log "Hoptoad Success: #{response.class}" - else - body = response.body if response.respond_to? :body - log "Hoptoad Failure: #{response.class}\n#{body}" - end + HoptoadNotifier.notify(exception, + :parameters => { + :payload_class => payload['class'].to_s, + :payload_args => payload['args'].inspect + } + ) end - def xml - x = Builder::XmlMarkup.new - x.instruct! - x.notice :version=>"2.0" do - x.tag! "api-key", api_key - x.notifier do - x.name "Resqueue" - x.version "0.1" - x.url "http://github.com/defunkt/resque" - end - x.error do - x.tag! "class", exception.class.name - x.message "#{exception.class.name}: #{exception.message}" - x.backtrace do - fill_in_backtrace_lines(x) - end - end - x.request do - x.url queue.to_s - x.component worker.to_s - x.params do - x.var :key=>"payload_class" do - x.text! payload["class"].to_s - end - x.var :key=>"payload_args" do - x.text! payload["args"].to_s - end - end - end - x.tag!("server-environment") do - x.tag!("project-root", "RAILS_ROOT") - x.tag!("environment-name",server_environment) - end - - end - end - - def fill_in_backtrace_lines(x) - Array(exception.backtrace).each do |unparsed_line| - _, file, number, method = unparsed_line.match(INPUT_FORMAT).to_a - x.line :file => file,:number => number - end - end - - def use_ssl? - self.class.secure - end - - def api_key - self.class.api_key - end - - def server_environment - return self.class.server_environment if self.class.server_environment - defined?(RAILS_ENV) ? RAILS_ENV : (ENV['RACK_ENV'] || 'development') - end end end end From cd0f19129c4655c122f92a60c33fa2dce5b95600 Mon Sep 17 00:00:00 2001 From: Ray Krueger Date: Wed, 11 May 2011 14:59:28 -0500 Subject: [PATCH 2/4] Add hoptoad_notifier dependency to the gemspec --- Gemfile.lock | 14 ++++++++++---- resque.gemspec | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1399ebb32..7bca1c976 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,8 @@ PATH remote: . specs: - resque (1.13.0) + resque (1.15.0) + hoptoad_notifier (~> 2.4.9) json (~> 1.4.6) redis-namespace (>= 0.10.0) sinatra (>= 0.9.2) @@ -10,17 +11,22 @@ PATH GEM remote: http://rubygems.org/ specs: + activesupport (3.0.7) + builder (3.0.0) + hoptoad_notifier (2.4.9) + activesupport + builder json (1.4.6) rack (1.2.2) rack-test (0.5.7) rack (>= 1.0) - redis (2.1.1) + redis (2.2.0) redis-namespace (0.10.0) redis (< 3.0.0) - sinatra (1.2.1) + sinatra (1.2.6) rack (~> 1.1) tilt (>= 1.2.2, < 2.0) - tilt (1.2.2) + tilt (1.3) vegas (0.1.8) rack (>= 1.0.0) diff --git a/resque.gemspec b/resque.gemspec index cb8e3b571..3c20df86d 100644 --- a/resque.gemspec +++ b/resque.gemspec @@ -25,6 +25,8 @@ Gem::Specification.new do |s| s.add_dependency "vegas", "~> 0.1.2" s.add_dependency "sinatra", ">= 0.9.2" s.add_dependency "json", "~> 1.4.6" + s.add_dependency "hoptoad_notifier","~> 2.4.9" + s.description = < Date: Wed, 11 May 2011 15:43:43 -0500 Subject: [PATCH 3/4] Use notify_or_ignore for the hoptoad failure backend Hoptoad can be configured with a set of exceptions to ignore. However, those exceptions are not ignored when using Hoptoad.notify alone; Hoptoad.notify_or_ignore must be used. --- lib/resque/failure/hoptoad.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/resque/failure/hoptoad.rb b/lib/resque/failure/hoptoad.rb index b1fd32c83..b377a1a96 100644 --- a/lib/resque/failure/hoptoad.rb +++ b/lib/resque/failure/hoptoad.rb @@ -27,7 +27,7 @@ def self.count end def save - HoptoadNotifier.notify(exception, + HoptoadNotifier.notify_or_ignore(exception, :parameters => { :payload_class => payload['class'].to_s, :payload_args => payload['args'].inspect From c41c9ca47166d2b87d11e7d1f0ed3b46ec2adbb9 Mon Sep 17 00:00:00 2001 From: Ray Krueger Date: Wed, 11 May 2011 16:17:43 -0500 Subject: [PATCH 4/4] Add a test for the hoptoad failure backend This class did not have a test previously, it's about time it got one. --- Gemfile | 1 + Gemfile.lock | 4 ++++ test/hoptoad_test.rb | 23 +++++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 test/hoptoad_test.rb diff --git a/Gemfile b/Gemfile index 0ef76a5b3..a50aea2f3 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,5 @@ gemspec group :test do gem "rack-test", "~> 0.5" + gem "mocha", "~> 0.9.7" end diff --git a/Gemfile.lock b/Gemfile.lock index 7bca1c976..025c87ccb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,9 +17,12 @@ GEM activesupport builder json (1.4.6) + mocha (0.9.7) + rake rack (1.2.2) rack-test (0.5.7) rack (>= 1.0) + rake (0.8.7) redis (2.2.0) redis-namespace (0.10.0) redis (< 3.0.0) @@ -34,5 +37,6 @@ PLATFORMS ruby DEPENDENCIES + mocha (~> 0.9.7) rack-test (~> 0.5) resque! diff --git a/test/hoptoad_test.rb b/test/hoptoad_test.rb new file mode 100644 index 000000000..653dc62f2 --- /dev/null +++ b/test/hoptoad_test.rb @@ -0,0 +1,23 @@ +require 'test_helper' +require 'resque/failure/hoptoad' +require 'mocha' +require 'hoptoad_notifier' + +context "Hoptoad" do + + test "should be notified of an error" do + exception = StandardError.new("BOOM") + worker = Resque::Worker.new(:test) + queue = "test" + payload = {'class' => Object, 'args' => 66} + + HoptoadNotifier.expects(:notify_or_ignore).with( + exception, + :parameters => {:payload_class => 'Object', :payload_args => '66'}) + + backend = Resque::Failure::Hoptoad.new(exception, worker, queue, payload) + backend.save + + end + +end