From 9e4546b92a87c3e464aa1b7f22ff29a085356c82 Mon Sep 17 00:00:00 2001 From: Jason Torres Date: Wed, 9 Mar 2011 15:07:59 +0800 Subject: [PATCH 1/6] Include the entire namespace so Rails can see it --- lib/bullhorn/sender.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bullhorn/sender.rb b/lib/bullhorn/sender.rb index f17d01d..826e1c0 100644 --- a/lib/bullhorn/sender.rb +++ b/lib/bullhorn/sender.rb @@ -7,7 +7,7 @@ def serialize(str) end def notify(exception, env = {}) - bt = Backtrace.new(exception, :context => @show_code_context) + bt = Bullhorn::Backtrace.new(exception, :context => @show_code_context) Net::HTTP.post_form(URI(url), { :api_key => api_key, From 28c38c2bd29bc2f6bdf238268c1aa430897ba344 Mon Sep 17 00:00:00 2001 From: Jason Torres Date: Wed, 9 Mar 2011 15:56:22 +0800 Subject: [PATCH 2/6] Support for stand-alone exception reporting --- lib/bullhorn.rb | 37 +++++++++++++++++++++++++++++++++++-- lib/bullhorn/backtrace.rb | 16 +++++++++------- lib/bullhorn/sender.rb | 5 +++-- test/test_bullhorn.rb | 8 +++++++- 4 files changed, 54 insertions(+), 12 deletions(-) diff --git a/lib/bullhorn.rb b/lib/bullhorn.rb index 04d0478..d68c699 100644 --- a/lib/bullhorn.rb +++ b/lib/bullhorn.rb @@ -11,7 +11,7 @@ class Bullhorn autoload :Backtrace, "bullhorn/backtrace" LANGUAGE = "ruby" - CLIENT_NAME = "bullhorn-ruby" + CLIENT_NAME = "bullhorn-ruby-test" VERSION = "0.1.0" URL = "http://www.bullhorn.it/api/v2/exception" @@ -28,7 +28,7 @@ class Bullhorn def initialize(app, options = {}) @app = app - @api_key = options[:api_key] || raise(ArgumentError, ":api_key is required") + @api_key = options[:api_key] || api_key || raise(ArgumentError, ":api_key is required") @filters = Array(options[:filters]) @url = options[:url] || URL @ignore_exceptions = Array(options[:ignore_exceptions] || default_ignore_exceptions) @@ -50,6 +50,39 @@ def call(env) [status, headers, body] end + class << self + def api_key=(key) + @@api_key = key + end + + def api_key + @@api_key + end + + + def notify_exception(exception) + + bt = Bullhorn::Backtrace.new(exception, :context => @show_code_context) + + Net::HTTP.post_form(URI(Bullhorn::URL), { + :api_key => api_key, + :message => exception.message, + :backtrace => Bullhorn::Sender.serialize(bt.to_a), + :env => Bullhorn::Sender.serialize(nil), + :request_body => Bullhorn::Sender.serialize(nil), + :sha1 => Bullhorn::Sender.sha1(exception), + # APIv2 + :language => Bullhorn::LANGUAGE, + :client_name => Bullhorn::CLIENT_NAME, + :client_version => Bullhorn::VERSION, + :url => "", + :class => exception.class.to_s + }) + + end + end + + protected def default_ignore_exceptions [].tap do |exceptions| diff --git a/lib/bullhorn/backtrace.rb b/lib/bullhorn/backtrace.rb index 850b0c9..4e5134c 100644 --- a/lib/bullhorn/backtrace.rb +++ b/lib/bullhorn/backtrace.rb @@ -2,7 +2,7 @@ class Bullhorn class Backtrace def initialize(exception, options = {}) @exception = exception - @raw = exception.backtrace # Array + @raw = exception.backtrace || [] # Array @options = { :context => true } @options.merge!(options) @@ -29,12 +29,14 @@ def get_context(fname, line, size = 2) def to_a @raw.inject([]) do |arr, line| - m = line.match(/^(?.+):(?[0-9]+):in `(?.*)'$/) - arr << { :function => m[:function], - :file => m[:file], - :line => m[:line], - :context => (@options[:context] ? get_context(m[:file], m[:line]) : nil) - } + m = line.match(/^(.+):([0-9]+):in `(.*)'$/) + + arr << { :function => m[3], + :file => m[1], + :line => m[2], + :context => (@options[:context] ? get_context(m[2], m[2]) : nil) + } if m + arr end end diff --git a/lib/bullhorn/sender.rb b/lib/bullhorn/sender.rb index 826e1c0..8cca471 100644 --- a/lib/bullhorn/sender.rb +++ b/lib/bullhorn/sender.rb @@ -25,15 +25,16 @@ def notify(exception, env = {}) }) end - protected def sha1(exception) # Treat 2 exceptions as the same if they match the same exception class # and same origin. salt = '#bh#' + Bullhorn::CLIENT_NAME - str = [ salt, exception.class.to_s, exception.backtrace.first ].join('|') + str = [ salt, exception.class.to_s, (exception.backtrace ? exception.backtrace.first : nil) ].join('|') Digest::SHA1.hexdigest(str) end + protected + def request_body(env) if io = env['rack.input'] io.rewind if io.respond_to?(:rewind) diff --git a/test/test_bullhorn.rb b/test/test_bullhorn.rb index ef59962..2d9a02a 100644 --- a/test/test_bullhorn.rb +++ b/test/test_bullhorn.rb @@ -11,6 +11,12 @@ class TestBullhorn < Test::Unit::TestCase end end + test "accept the api key from class level" do + Bullhorn.api_key = "key" + Bullhorn.new(@app) + assert_equal Bullhorn.api_key, "key" + end + test "accepts a filter of string arrays" do bullhorn = Bullhorn.new(@app, :api_key => "key", :filters => ['a', 'b']) assert_equal ['a', 'b'], bullhorn.filters @@ -182,4 +188,4 @@ module ::ActionController assert bh.ignore_exceptions.include?(ActionController::RoutingError) end end -end \ No newline at end of file +end From 8502d88f59af7472454c13f8256a7ef48cb91244 Mon Sep 17 00:00:00 2001 From: Jason Torres Date: Wed, 9 Mar 2011 15:57:11 +0800 Subject: [PATCH 3/6] Rollback the CLIENT_NAME :p --- lib/bullhorn.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bullhorn.rb b/lib/bullhorn.rb index d68c699..c3a74ca 100644 --- a/lib/bullhorn.rb +++ b/lib/bullhorn.rb @@ -11,7 +11,7 @@ class Bullhorn autoload :Backtrace, "bullhorn/backtrace" LANGUAGE = "ruby" - CLIENT_NAME = "bullhorn-ruby-test" + CLIENT_NAME = "bullhorn-ruby" VERSION = "0.1.0" URL = "http://www.bullhorn.it/api/v2/exception" From 8d9f1895cdc6c8a3bef75e7c88f57dd2c7803ccf Mon Sep 17 00:00:00 2001 From: Jason Torres Date: Wed, 9 Mar 2011 16:16:38 +0800 Subject: [PATCH 4/6] Add a trace. Not werkin. --- lib/bullhorn.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/bullhorn.rb b/lib/bullhorn.rb index c3a74ca..1c9410d 100644 --- a/lib/bullhorn.rb +++ b/lib/bullhorn.rb @@ -64,12 +64,12 @@ def notify_exception(exception) bt = Bullhorn::Backtrace.new(exception, :context => @show_code_context) - Net::HTTP.post_form(URI(Bullhorn::URL), { + post_options = { :api_key => api_key, :message => exception.message, :backtrace => Bullhorn::Sender.serialize(bt.to_a), - :env => Bullhorn::Sender.serialize(nil), - :request_body => Bullhorn::Sender.serialize(nil), + :env => Bullhorn::Sender.serialize({}), + :request_body => Bullhorn::Sender.serialize(""), :sha1 => Bullhorn::Sender.sha1(exception), # APIv2 :language => Bullhorn::LANGUAGE, @@ -77,7 +77,10 @@ def notify_exception(exception) :client_version => Bullhorn::VERSION, :url => "", :class => exception.class.to_s - }) + } + + puts post_options.inspect + Net::HTTP.post_form(URI(Bullhorn::URL), post_options) end end From a51ec4bf97361702d807803331aaa8568ed5986f Mon Sep 17 00:00:00 2001 From: Jason Torres Date: Wed, 9 Mar 2011 16:30:55 +0800 Subject: [PATCH 5/6] Truncate the string on the message body so it doesn't break the backend --- .gitignore | 1 + lib/bullhorn.rb | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f979985..bab9d46 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ tmtags .\#* ## VIM +*.swo *.swp ## PROJECT::GENERAL diff --git a/lib/bullhorn.rb b/lib/bullhorn.rb index 1c9410d..64b7caf 100644 --- a/lib/bullhorn.rb +++ b/lib/bullhorn.rb @@ -66,7 +66,7 @@ def notify_exception(exception) post_options = { :api_key => api_key, - :message => exception.message, + :message => exception.message[0..100], :backtrace => Bullhorn::Sender.serialize(bt.to_a), :env => Bullhorn::Sender.serialize({}), :request_body => Bullhorn::Sender.serialize(""), @@ -79,7 +79,6 @@ def notify_exception(exception) :class => exception.class.to_s } - puts post_options.inspect Net::HTTP.post_form(URI(Bullhorn::URL), post_options) end From 59ba56cbda520f003a1f4a0e248260fb1c0525ad Mon Sep 17 00:00:00 2001 From: Jason Torres Date: Wed, 9 Mar 2011 16:40:49 +0800 Subject: [PATCH 6/6] Put the filters, show_code_context on the class level also --- lib/bullhorn.rb | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/bullhorn.rb b/lib/bullhorn.rb index 64b7caf..56f5603 100644 --- a/lib/bullhorn.rb +++ b/lib/bullhorn.rb @@ -28,11 +28,11 @@ class Bullhorn def initialize(app, options = {}) @app = app - @api_key = options[:api_key] || api_key || raise(ArgumentError, ":api_key is required") - @filters = Array(options[:filters]) + @api_key = options[:api_key] || @@api_key || raise(ArgumentError, ":api_key is required") + @filters = Array(options[:filters] || @@filters) @url = options[:url] || URL @ignore_exceptions = Array(options[:ignore_exceptions] || default_ignore_exceptions) - @show_code_context = (options[:show_code_context].nil? ? true : options[:show_code_context]) + @show_code_context = (options[:show_code_context].nil? ? (@@show_code_context || true) : options[:show_code_context]) end def call(env) @@ -51,14 +51,31 @@ def call(env) end class << self + def api_key=(key) @@api_key = key end - + def api_key @@api_key end + def filters=(val) + @@filters = val + end + + def filters + @@filters + end + + def show_code_context=(val) + @@show_code_context + end + + def show_code_context + @@show_code_context + end + def notify_exception(exception)