honeybadger 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Appraisals +20 -0
- data/Gemfile +1 -13
- data/Gemfile.lock +39 -64
- data/MIT-LICENSE +5 -0
- data/README.md +102 -3
- data/Rakefile +9 -134
- data/features/metal.feature +6 -4
- data/features/rack.feature +3 -4
- data/features/rails.feature +106 -99
- data/features/rake.feature +0 -2
- data/features/sinatra.feature +1 -3
- data/features/step_definitions/metal_steps.rb +2 -1
- data/features/step_definitions/rack_steps.rb +2 -2
- data/features/step_definitions/rails_steps.rb +238 -0
- data/features/step_definitions/rake_steps.rb +1 -1
- data/features/support/env.rb +7 -7
- data/features/support/rails.rb +41 -58
- data/gemfiles/rails2.3.gemfile +9 -0
- data/gemfiles/rails2.3.gemfile.lock +102 -0
- data/gemfiles/rails3.0.gemfile +8 -0
- data/gemfiles/rails3.0.gemfile.lock +146 -0
- data/gemfiles/rails3.1.gemfile +8 -0
- data/gemfiles/rails3.1.gemfile.lock +161 -0
- data/gemfiles/rails3.2.gemfile +8 -0
- data/gemfiles/rails3.2.gemfile.lock +160 -0
- data/honeybadger.gemspec +30 -24
- data/lib/honeybadger.rb +117 -113
- data/lib/honeybadger/backtrace.rb +9 -3
- data/lib/honeybadger/configuration.rb +22 -0
- data/lib/honeybadger/notice.rb +9 -0
- data/lib/honeybadger/rack.rb +5 -4
- data/lib/honeybadger/rails3_tasks.rb +20 -23
- data/lib/honeybadger/sender.rb +10 -4
- data/lib/honeybadger/shared_tasks.rb +12 -1
- data/lib/honeybadger/tasks.rb +6 -1
- data/test/test_helper.rb +71 -71
- data/test/unit/backtrace_test.rb +26 -23
- data/test/unit/capistrano_test.rb +1 -1
- data/test/unit/configuration_test.rb +19 -3
- data/test/unit/honeybadger_tasks_test.rb +1 -1
- data/test/unit/logger_test.rb +1 -1
- data/test/unit/notice_test.rb +71 -16
- data/test/unit/notifier_test.rb +25 -5
- data/test/unit/rack_test.rb +21 -1
- data/test/unit/rails/action_controller_catcher_test.rb +1 -1
- data/test/unit/rails_test.rb +1 -1
- data/test/unit/sender_test.rb +1 -1
- metadata +69 -45
- data/SUPPORTED_RAILS_VERSIONS +0 -37
- data/TESTING.md +0 -33
- data/features/step_definitions/file_steps.rb +0 -10
- data/features/step_definitions/rails_application_steps.rb +0 -394
- data/features/support/terminal.rb +0 -107
@@ -4,7 +4,7 @@ module Honeybadger
|
|
4
4
|
|
5
5
|
# Public: Handles backtrace parsing line by line
|
6
6
|
class Line
|
7
|
-
# regexp (
|
7
|
+
# regexp (optionally allowing leading X: for windows support)
|
8
8
|
INPUT_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}.freeze
|
9
9
|
|
10
10
|
# Public: The file portion of the line (such as app/models/user.rb)
|
@@ -62,6 +62,11 @@ module Honeybadger
|
|
62
62
|
"<Line:#{to_s}>"
|
63
63
|
end
|
64
64
|
|
65
|
+
# Public: Determines if this line is part of the application trace or not
|
66
|
+
def application?
|
67
|
+
(filtered_file =~ /^\[PROJECT_ROOT\]/i) && !(filtered_file =~ /^\[PROJECT_ROOT\]\/vendor/i)
|
68
|
+
end
|
69
|
+
|
65
70
|
# Public: An excerpt from the source file, lazily loaded to preserve
|
66
71
|
# performance
|
67
72
|
def source(radius = 2)
|
@@ -94,7 +99,7 @@ module Honeybadger
|
|
94
99
|
end
|
95
100
|
|
96
101
|
# Public: holder for an Array of Backtrace::Line instances
|
97
|
-
attr_reader :lines
|
102
|
+
attr_reader :lines, :application_lines
|
98
103
|
|
99
104
|
def self.parse(ruby_backtrace, opts = {})
|
100
105
|
ruby_lines = split_multiline_backtrace(ruby_backtrace)
|
@@ -108,6 +113,7 @@ module Honeybadger
|
|
108
113
|
|
109
114
|
def initialize(lines)
|
110
115
|
self.lines = lines
|
116
|
+
self.application_lines = lines.select(&:application?)
|
111
117
|
end
|
112
118
|
|
113
119
|
# Public
|
@@ -146,7 +152,7 @@ module Honeybadger
|
|
146
152
|
|
147
153
|
private
|
148
154
|
|
149
|
-
attr_writer :lines
|
155
|
+
attr_writer :lines, :application_lines
|
150
156
|
|
151
157
|
def self.split_multiline_backtrace(backtrace)
|
152
158
|
if backtrace.to_a.size == 1
|
@@ -91,6 +91,9 @@ module Honeybadger
|
|
91
91
|
# The radius around trace line to include in source excerpt
|
92
92
|
attr_accessor :source_extract_radius
|
93
93
|
|
94
|
+
# A Proc object used to send notices asynchronously
|
95
|
+
attr_writer :async
|
96
|
+
|
94
97
|
DEFAULT_PARAMS_FILTERS = %w(password password_confirmation).freeze
|
95
98
|
|
96
99
|
DEFAULT_BACKTRACE_FILTERS = [
|
@@ -231,6 +234,25 @@ module Honeybadger
|
|
231
234
|
!development_environments.include?(environment_name)
|
232
235
|
end
|
233
236
|
|
237
|
+
# Public: Configure async delivery
|
238
|
+
#
|
239
|
+
# block - An optional block containing an async handler
|
240
|
+
#
|
241
|
+
# Examples
|
242
|
+
#
|
243
|
+
# config.async = Proc.new { |notice| Thread.new { notice.deliver } }
|
244
|
+
#
|
245
|
+
# config.async do |notice|
|
246
|
+
# Thread.new { notice.deliver }
|
247
|
+
# end
|
248
|
+
#
|
249
|
+
# Returns configured async handler (should respond to #call(notice))
|
250
|
+
def async
|
251
|
+
@async = Proc.new if block_given?
|
252
|
+
@async
|
253
|
+
end
|
254
|
+
alias :async? :async
|
255
|
+
|
234
256
|
def port
|
235
257
|
@port || default_port
|
236
258
|
end
|
data/lib/honeybadger/notice.rb
CHANGED
@@ -114,6 +114,13 @@ module Honeybadger
|
|
114
114
|
set_context
|
115
115
|
end
|
116
116
|
|
117
|
+
# Public: Send the notice to Honeybadger using the configured sender
|
118
|
+
#
|
119
|
+
# Returns a reference to the error in Honeybadger
|
120
|
+
def deliver
|
121
|
+
Honeybadger.sender.send_to_honeybadger(to_json)
|
122
|
+
end
|
123
|
+
|
117
124
|
# Public: Template used to create JSON payload
|
118
125
|
#
|
119
126
|
# Returns JSON representation of notice
|
@@ -274,6 +281,8 @@ module Honeybadger
|
|
274
281
|
parts = line.split(': ')
|
275
282
|
[parts[0].strip, parts[1] || '']
|
276
283
|
end]
|
284
|
+
elsif backtrace.application_lines.any?
|
285
|
+
backtrace.application_lines.first.source(source_extract_radius)
|
277
286
|
else
|
278
287
|
backtrace.lines.first.source(source_extract_radius)
|
279
288
|
end
|
data/lib/honeybadger/rack.rb
CHANGED
@@ -34,21 +34,22 @@ module Honeybadger
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def notify_honeybadger(exception,env)
|
37
|
-
Honeybadger.notify_or_ignore(exception
|
37
|
+
Honeybadger.notify_or_ignore(exception, :rack_env => env) unless ignored_user_agent?(env)
|
38
38
|
end
|
39
39
|
|
40
40
|
def call(env)
|
41
41
|
begin
|
42
42
|
response = @app.call(env)
|
43
43
|
rescue Exception => raised
|
44
|
-
env['honeybadger.error_id'] = notify_honeybadger(raised,env)
|
44
|
+
env['honeybadger.error_id'] = notify_honeybadger(raised, env)
|
45
45
|
raise
|
46
46
|
ensure
|
47
47
|
Honeybadger.context.clear!
|
48
48
|
end
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
framework_exception = env['rack.exception'] || env['sinatra.error']
|
51
|
+
if framework_exception
|
52
|
+
env['honeybadger.error_id'] = notify_honeybadger(framework_exception, env)
|
52
53
|
end
|
53
54
|
|
54
55
|
response
|
@@ -3,16 +3,26 @@ require File.join(File.dirname(__FILE__), 'shared_tasks')
|
|
3
3
|
|
4
4
|
namespace :honeybadger do
|
5
5
|
desc "Verify your gem installation by sending a test exception to the honeybadger service"
|
6
|
-
task :test =>
|
7
|
-
Rails.logger = defined?(ActiveSupport::TaggedLogging)
|
8
|
-
|
9
|
-
|
6
|
+
task :test => :environment do
|
7
|
+
Rails.logger = if defined?(ActiveSupport::TaggedLogging)
|
8
|
+
ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
|
9
|
+
else
|
10
|
+
Logger.new(STDOUT)
|
11
|
+
end
|
12
|
+
Rails.logger.level = Logger::INFO
|
10
13
|
|
11
|
-
Rails.logger.level = Logger::DEBUG
|
12
14
|
Honeybadger.configure(true) do |config|
|
13
15
|
config.logger = Rails.logger
|
14
16
|
end
|
15
17
|
|
18
|
+
# Suppress error logging in Rails' exception handling middleware. Rails 3.0
|
19
|
+
# uses ActionDispatch::ShowExceptions to rescue/show exceptions, but does
|
20
|
+
# not log anything but application trace. Rails 3.2 now falls back to
|
21
|
+
# logging the framework trace (moved to ActionDispatch::DebugExceptions),
|
22
|
+
# which caused cluttered output while running the test task.
|
23
|
+
class ActionDispatch::DebugExceptions ; def logger(*args) ; @logger ||= Logger.new('/dev/null') ; end ; end
|
24
|
+
class ActionDispatch::ShowExceptions ; def logger(*args) ; @logger ||= Logger.new('/dev/null') ; end ; end
|
25
|
+
|
16
26
|
require './app/controllers/application_controller'
|
17
27
|
|
18
28
|
class HoneybadgerTestingException < RuntimeError; end
|
@@ -22,6 +32,11 @@ namespace :honeybadger do
|
|
22
32
|
exit
|
23
33
|
end
|
24
34
|
|
35
|
+
if Honeybadger.configuration.async?
|
36
|
+
puts "Temporarily disabling asynchronous delivery"
|
37
|
+
Honeybadger.configuration.async = nil
|
38
|
+
end
|
39
|
+
|
25
40
|
Honeybadger.configuration.development_environments = []
|
26
41
|
|
27
42
|
puts "Configuration:"
|
@@ -43,35 +58,17 @@ namespace :honeybadger do
|
|
43
58
|
raise exception_class.new, 'Testing honeybadger via "rake honeybadger:test". If you can see this, it works.'
|
44
59
|
end
|
45
60
|
|
46
|
-
# def rescue_action(exception)
|
47
|
-
# rescue_action_in_public exception
|
48
|
-
# end
|
49
|
-
|
50
61
|
# Ensure we actually have an action to go to.
|
51
62
|
def verify; end
|
52
63
|
|
53
|
-
# def consider_all_requests_local
|
54
|
-
# false
|
55
|
-
# end
|
56
|
-
|
57
|
-
# def local_request?
|
58
|
-
# false
|
59
|
-
# end
|
60
|
-
|
61
64
|
def exception_class
|
62
65
|
exception_name = ENV['EXCEPTION'] || "HoneybadgerTestingException"
|
63
66
|
Object.const_get(exception_name)
|
64
67
|
rescue
|
65
68
|
Object.const_set(exception_name, Class.new(Exception))
|
66
69
|
end
|
67
|
-
|
68
|
-
def logger
|
69
|
-
nil
|
70
|
-
end
|
71
70
|
end
|
72
|
-
class HoneybadgerVerificationController < ApplicationController; end
|
73
71
|
|
74
|
-
Rails.application.routes_reloader.execute_if_updated
|
75
72
|
Rails.application.routes.draw do
|
76
73
|
match 'verify' => 'application#verify', :as => 'verify'
|
77
74
|
end
|
data/lib/honeybadger/sender.rb
CHANGED
@@ -48,9 +48,9 @@ module Honeybadger
|
|
48
48
|
|
49
49
|
case response
|
50
50
|
when Net::HTTPSuccess then
|
51
|
-
log(:info, "Success: #{response.class}", response)
|
51
|
+
log(:info, "Success: #{response.class}", response, data)
|
52
52
|
else
|
53
|
-
log(:error, "Failure: #{response.class}", response)
|
53
|
+
log(:error, "Failure: #{response.class}", response, data)
|
54
54
|
end
|
55
55
|
|
56
56
|
if response && response.respond_to?(:body)
|
@@ -84,8 +84,14 @@ module Honeybadger
|
|
84
84
|
URI.parse("#{protocol}://#{host}:#{port}").merge(NOTICES_URI)
|
85
85
|
end
|
86
86
|
|
87
|
-
def log(level, message, response = nil)
|
88
|
-
|
87
|
+
def log(level, message, response = nil, data = nil)
|
88
|
+
if logger
|
89
|
+
logger.send(level, LOG_PREFIX + message)
|
90
|
+
|
91
|
+
# Log the notice payload for debugging
|
92
|
+
logger.debug(LOG_PREFIX + "Notice: #{data}") if data
|
93
|
+
end
|
94
|
+
|
89
95
|
Honeybadger.report_environment_info
|
90
96
|
Honeybadger.report_response_body(response.body) if response && response.respond_to?(:body)
|
91
97
|
end
|
@@ -1,7 +1,18 @@
|
|
1
1
|
namespace :honeybadger do
|
2
2
|
desc "Notify Honeybadger of a new deploy."
|
3
|
-
task :deploy
|
3
|
+
task :deploy do
|
4
4
|
require 'honeybadger_tasks'
|
5
|
+
|
6
|
+
if defined?(Rails.root)
|
7
|
+
initializer_file = Rails.root.join('config', 'initializers','honeybadger.rb')
|
8
|
+
|
9
|
+
if initializer_file.exist?
|
10
|
+
load initializer_file
|
11
|
+
else
|
12
|
+
Rake::Task[:environment].invoke
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
5
16
|
HoneybadgerTasks.deploy(:environment => ENV['TO'],
|
6
17
|
:revision => ENV['REVISION'],
|
7
18
|
:repository => ENV['REPO'],
|
data/lib/honeybadger/tasks.rb
CHANGED
@@ -4,7 +4,7 @@ require File.join(File.dirname(__FILE__), 'shared_tasks')
|
|
4
4
|
namespace :honeybadger do
|
5
5
|
desc "Verify your gem installation by sending a test exception to the honeybadger service"
|
6
6
|
task :test => ['honeybadger:log_stdout', :environment] do
|
7
|
-
RAILS_DEFAULT_LOGGER.level = Logger::
|
7
|
+
RAILS_DEFAULT_LOGGER.level = Logger::INFO
|
8
8
|
|
9
9
|
require 'action_controller/test_process'
|
10
10
|
|
@@ -17,6 +17,11 @@ namespace :honeybadger do
|
|
17
17
|
exit
|
18
18
|
end
|
19
19
|
|
20
|
+
if Honeybadger.configuration.async?
|
21
|
+
puts "Temporarily disabling asynchronous delivery"
|
22
|
+
Honeybadger.configuration.async = nil
|
23
|
+
end
|
24
|
+
|
20
25
|
Honeybadger.configuration.development_environments = []
|
21
26
|
|
22
27
|
catcher = Honeybadger::Rails::ActionControllerCatcher
|
data/test/test_helper.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
|
3
|
-
require 'bundler/setup'
|
4
|
-
|
5
3
|
require 'mocha'
|
6
4
|
require 'shoulda'
|
7
5
|
require 'bourne'
|
@@ -27,14 +25,12 @@ end
|
|
27
25
|
module DefinesConstants
|
28
26
|
def setup
|
29
27
|
@defined_constants = []
|
30
|
-
Honeybadger.context.clear!
|
31
28
|
end
|
32
29
|
|
33
30
|
def teardown
|
34
31
|
@defined_constants.each do |constant|
|
35
32
|
Object.__send__(:remove_const, constant)
|
36
33
|
end
|
37
|
-
Honeybadger.context.clear!
|
38
34
|
end
|
39
35
|
|
40
36
|
def define_constant(name, value)
|
@@ -55,91 +51,95 @@ class CollectingSender
|
|
55
51
|
end
|
56
52
|
end
|
57
53
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
54
|
+
class Test::Unit::TestCase
|
55
|
+
def teardown
|
56
|
+
Honeybadger.context.clear!
|
57
|
+
end
|
63
58
|
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
def assert_no_difference(expression, message = nil, &block)
|
60
|
+
assert_difference expression, 0, message, &block
|
61
|
+
end
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
def stub_sender
|
64
|
+
stub('sender', :send_to_honeybadger => nil)
|
65
|
+
end
|
66
|
+
|
67
|
+
def stub_sender!
|
68
|
+
Honeybadger.sender = stub_sender
|
69
|
+
end
|
71
70
|
|
72
|
-
|
73
|
-
|
71
|
+
def stub_notice
|
72
|
+
Honeybadger::Notice.new({}).tap do |notice|
|
73
|
+
notice.stubs(:ignored? => false, :to_json => '{"foo":"bar"}')
|
74
74
|
end
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
77
|
+
def stub_notice!
|
78
|
+
stub_notice.tap do |notice|
|
79
|
+
Honeybadger::Notice.stubs(:new => notice)
|
80
80
|
end
|
81
|
+
end
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
83
|
+
def reset_config
|
84
|
+
Honeybadger.configuration = nil
|
85
|
+
Honeybadger.configure do |config|
|
86
|
+
config.api_key = 'abc123'
|
87
87
|
end
|
88
|
+
end
|
88
89
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
}
|
90
|
+
def build_notice_data(exception = nil)
|
91
|
+
exception ||= build_exception
|
92
|
+
{
|
93
|
+
:api_key => 'abc123',
|
94
|
+
:error_class => exception.class.name,
|
95
|
+
:error_message => "#{exception.class.name}: #{exception.message}",
|
96
|
+
:backtrace => exception.backtrace,
|
97
|
+
:environment => { 'PATH' => '/bin', 'REQUEST_URI' => '/users/1' },
|
98
|
+
:request => {
|
99
|
+
:params => { 'controller' => 'users', 'action' => 'show', 'id' => '1' },
|
100
|
+
:rails_root => '/path/to/application',
|
101
|
+
:url => "http://test.host/users/1"
|
102
|
+
},
|
103
|
+
:session => {
|
104
|
+
:key => '123abc',
|
105
|
+
:data => { 'user_id' => '5', 'flash' => { 'notice' => 'Logged in successfully' } }
|
106
106
|
}
|
107
|
-
|
107
|
+
}
|
108
|
+
end
|
108
109
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
110
|
+
def build_exception(opts = {})
|
111
|
+
backtrace = ["test/honeybadger/rack_test.rb:15:in `build_exception'",
|
112
|
+
"test/honeybadger/rack_test.rb:52:in `test_delivers_exception_from_rack'",
|
113
|
+
"/Users/josh/Developer/.rvm/gems/ruby-1.9.3-p0/gems/mocha-0.10.5/lib/mocha/integration/mini_test/version_230_to_262.rb:28:in `run'"]
|
114
|
+
opts = { :backtrace => backtrace }.merge(opts)
|
115
|
+
BacktracedException.new(opts)
|
116
|
+
end
|
116
117
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
end
|
118
|
+
def assert_array_starts_with(expected, actual)
|
119
|
+
assert_respond_to actual, :to_ary
|
120
|
+
array = actual.to_ary.reverse
|
121
|
+
expected.reverse.each_with_index do |value, i|
|
122
|
+
assert_equal value, array[i]
|
123
123
|
end
|
124
|
+
end
|
124
125
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
126
|
+
def assert_logged(expected)
|
127
|
+
assert_received(Honeybadger, :write_verbose_log) do |expect|
|
128
|
+
expect.with {|actual| actual =~ expected }
|
129
129
|
end
|
130
|
+
end
|
130
131
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
132
|
+
def assert_not_logged(expected)
|
133
|
+
assert_received(Honeybadger, :write_verbose_log) do |expect|
|
134
|
+
expect.with {|actual| actual =~ expected }.never
|
135
135
|
end
|
136
|
+
end
|
136
137
|
|
137
|
-
|
138
|
-
|
139
|
-
|
138
|
+
def assert_caught_and_sent
|
139
|
+
assert !Honeybadger.sender.collected.empty?
|
140
|
+
end
|
140
141
|
|
141
|
-
|
142
|
-
|
143
|
-
end
|
142
|
+
def assert_caught_and_not_sent
|
143
|
+
assert Honeybadger.sender.collected.empty?
|
144
144
|
end
|
145
145
|
end
|