honeybadger 2.7.2 → 3.0.0.beta1

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +58 -3
  3. data/README.md +8 -15
  4. data/lib/honeybadger.rb +9 -232
  5. data/lib/honeybadger/agent.rb +292 -134
  6. data/lib/honeybadger/backend.rb +6 -6
  7. data/lib/honeybadger/backend/base.rb +11 -0
  8. data/lib/honeybadger/backend/server.rb +2 -14
  9. data/lib/honeybadger/cli.rb +0 -2
  10. data/lib/honeybadger/cli/deploy.rb +42 -0
  11. data/lib/honeybadger/cli/exec.rb +138 -0
  12. data/lib/honeybadger/cli/heroku.rb +1 -22
  13. data/lib/honeybadger/cli/install.rb +74 -0
  14. data/lib/honeybadger/cli/main.rb +138 -153
  15. data/lib/honeybadger/cli/notify.rb +66 -0
  16. data/lib/honeybadger/cli/test.rb +266 -0
  17. data/lib/honeybadger/config.rb +178 -162
  18. data/lib/honeybadger/config/defaults.rb +5 -5
  19. data/lib/honeybadger/config/env.rb +8 -6
  20. data/lib/honeybadger/config/ruby.rb +100 -0
  21. data/lib/honeybadger/config/yaml.rb +18 -19
  22. data/lib/honeybadger/const.rb +3 -16
  23. data/lib/honeybadger/context_manager.rb +50 -0
  24. data/lib/honeybadger/init/rails.rb +9 -21
  25. data/lib/honeybadger/init/rake.rb +2 -0
  26. data/lib/honeybadger/init/ruby.rb +9 -0
  27. data/lib/honeybadger/init/sinatra.rb +13 -6
  28. data/lib/honeybadger/notice.rb +29 -14
  29. data/lib/honeybadger/plugins/delayed_job/plugin.rb +4 -5
  30. data/lib/honeybadger/plugins/passenger.rb +1 -2
  31. data/lib/honeybadger/plugins/rails.rb +0 -28
  32. data/lib/honeybadger/plugins/resque.rb +2 -5
  33. data/lib/honeybadger/plugins/shoryuken.rb +2 -2
  34. data/lib/honeybadger/plugins/sidekiq.rb +2 -2
  35. data/lib/honeybadger/plugins/sucker_punch.rb +1 -0
  36. data/lib/honeybadger/plugins/thor.rb +2 -2
  37. data/lib/honeybadger/plugins/warden.rb +1 -0
  38. data/lib/honeybadger/rack/error_notifier.rb +11 -9
  39. data/lib/honeybadger/rack/user_feedback.rb +6 -4
  40. data/lib/honeybadger/rack/user_informer.rb +6 -4
  41. data/lib/honeybadger/ruby.rb +2 -0
  42. data/lib/honeybadger/singleton.rb +26 -0
  43. data/lib/honeybadger/util/http.rb +12 -0
  44. data/lib/honeybadger/util/request_hash.rb +71 -0
  45. data/lib/honeybadger/util/sanitizer.rb +101 -64
  46. data/lib/honeybadger/version.rb +1 -1
  47. data/lib/honeybadger/worker.rb +246 -0
  48. metadata +17 -13
  49. data/lib/honeybadger/agent/batch.rb +0 -50
  50. data/lib/honeybadger/agent/null_worker.rb +0 -26
  51. data/lib/honeybadger/agent/worker.rb +0 -243
  52. data/lib/honeybadger/cli/helpers.rb +0 -160
  53. data/lib/honeybadger/config/callbacks.rb +0 -70
  54. data/lib/honeybadger/plugins/unicorn.rb +0 -27
  55. data/lib/honeybadger/rack/metrics_reporter.rb +0 -16
  56. data/lib/honeybadger/rack/request_hash.rb +0 -55
@@ -1,160 +0,0 @@
1
- require 'logger'
2
-
3
- module Honeybadger
4
- module CLI
5
- module Helpers
6
- def rails?(opts = {})
7
- @rails ||= load_rails(opts)
8
- end
9
-
10
- def load_rails(opts = {})
11
- begin
12
- require 'honeybadger/init/rails'
13
- if ::Rails::VERSION::MAJOR >= 3
14
- say("Detected Rails #{::Rails::VERSION::STRING}") if opts[:verbose]
15
- else
16
- say("Error: Rails #{::Rails::VERSION::STRING} is unsupported.", :red)
17
- exit(1)
18
- end
19
- rescue LoadError
20
- say("Rails was not detected, loading standalone.") if opts[:verbose]
21
- return @rails = false
22
- rescue StandardError => e
23
- say("Error while detecting Rails: #{e.class} -- #{e.message}", :red)
24
- exit(1)
25
- end
26
-
27
- begin
28
- require File.expand_path('config/application')
29
- rescue LoadError
30
- say('Error: could not load Rails application. Please ensure you run this command from your project root.', :red)
31
- exit(1)
32
- end
33
-
34
- @rails = true
35
- end
36
-
37
- def load_rails_env(opts = {})
38
- return false unless rails?(opts)
39
-
40
- puts('Loading Rails environment') if opts[:verbose]
41
- ::Rails.application.require_environment!
42
-
43
- true
44
- end
45
-
46
- def rails_framework_opts
47
- return {} unless defined?(::Rails)
48
-
49
- {
50
- :root => ::Rails.root,
51
- :env => ::Rails.env,
52
- :'config.path' => ::Rails.root.join('config', 'honeybadger.yml'),
53
- :framework => :rails
54
- }
55
- end
56
-
57
- def test_exception_class
58
- exception_name = ENV['EXCEPTION'] || 'HoneybadgerTestingException'
59
- Object.const_get(exception_name)
60
- rescue
61
- Object.const_set(exception_name, Class.new(Exception))
62
- end
63
-
64
- def send_test(verbose = true)
65
- if defined?(::Rails)
66
- rails_test(verbose)
67
- else
68
- standalone_test
69
- end
70
- end
71
-
72
- def standalone_test
73
- Honeybadger.notify(test_exception_class.new('Testing honeybadger via "honeybadger test". If you can see this, it works.'))
74
- end
75
-
76
- def rails_test(verbose = true)
77
- if verbose
78
- ::Rails.logger = if defined?(::ActiveSupport::TaggedLogging)
79
- ::ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
80
- else
81
- Logger.new(STDOUT)
82
- end
83
- ::Rails.logger.level = Logger::INFO
84
- end
85
-
86
- # Suppress error logging in Rails' exception handling middleware. Rails 3.0
87
- # uses ActionDispatch::ShowExceptions to rescue/show exceptions, but does
88
- # not log anything but application trace. Rails 3.2 now falls back to
89
- # logging the framework trace (moved to ActionDispatch::DebugExceptions),
90
- # which caused cluttered output while running the test task.
91
- defined?(::ActionDispatch::DebugExceptions) and
92
- ::ActionDispatch::DebugExceptions.class_eval { def logger(*args) ; @logger ||= Logger.new('/dev/null') ; end }
93
- defined?(::ActionDispatch::ShowExceptions) and
94
- ::ActionDispatch::ShowExceptions.class_eval { def logger(*args) ; @logger ||= Logger.new('/dev/null') ; end }
95
-
96
- # Detect and disable the better_errors gem
97
- if defined?(::BetterErrors::Middleware)
98
- say('Better Errors detected: temporarily disabling middleware.', :yellow)
99
- ::BetterErrors::Middleware.class_eval { def call(env) @app.call(env); end }
100
- end
101
-
102
- begin
103
- require './app/controllers/application_controller'
104
- rescue LoadError
105
- nil
106
- end
107
-
108
- unless defined?(::ApplicationController)
109
- say('Error: No ApplicationController found.', :red)
110
- return false
111
- end
112
-
113
- say('Setting up the Controller.')
114
- eval(<<-CONTROLLER)
115
- class Honeybadger::TestController < ApplicationController
116
- # This is to bypass any filters that may prevent access to the action.
117
- if respond_to?(:prepend_before_action)
118
- prepend_before_action :test_honeybadger
119
- else
120
- prepend_before_filter :test_honeybadger
121
- end
122
-
123
- def test_honeybadger
124
- puts "Raising '#{test_exception_class.name}' to simulate application failure."
125
- raise #{test_exception_class}.new, 'Testing honeybadger via "honeybadger test", it works.'
126
- end
127
-
128
- # Ensure we actually have an action to go to.
129
- def verify; end
130
- end
131
- CONTROLLER
132
-
133
- ::Rails.application.routes.tap do |r|
134
- # RouteSet#disable_clear_and_finalize prevents existing routes from
135
- # being cleared. We'll set it back to the original value when we're
136
- # done so not to mess with Rails state.
137
- d = r.disable_clear_and_finalize
138
- begin
139
- r.disable_clear_and_finalize = true
140
- r.clear!
141
- r.draw do
142
- match 'verify' => 'honeybadger/test#verify', :as => 'verify', :via => :get
143
- end
144
- ::Rails.application.routes_reloader.paths.each{ |path| load(path) }
145
- ::ActiveSupport.on_load(:action_controller) { r.finalize! }
146
- ensure
147
- r.disable_clear_and_finalize = d
148
- end
149
- end
150
-
151
- say('Processing request.')
152
-
153
- ssl = defined?(::Rails.configuration.force_ssl) && ::Rails.configuration.force_ssl
154
- env = ::Rack::MockRequest.env_for("http#{ ssl ? 's' : nil }://www.example.com/verify", 'REMOTE_ADDR' => '127.0.0.1')
155
-
156
- ::Rails.application.call(env)
157
- end
158
- end
159
- end
160
- end
@@ -1,70 +0,0 @@
1
- module Honeybadger
2
- class Config
3
- class Callbacks
4
- attr_reader :backtrace_filter, :exception_filter, :exception_fingerprint
5
-
6
- def initialize
7
- @backtrace_filter = nil
8
- @exception_filter = nil
9
- @exception_fingerprint = nil
10
- end
11
-
12
- # Public: Takes a block and adds it to the list of backtrace filters. When
13
- # the filters run, the block will be handed each line of the backtrace and
14
- # can modify it as necessary.
15
- #
16
- # &block - The new backtrace filter.
17
- #
18
- # Examples:
19
- #
20
- # config.backtrace_filter do |line|
21
- # line.gsub(/^#{Rails.root}/, "[Rails.root]")
22
- # end
23
- #
24
- # Yields a line in the backtrace.
25
- def backtrace_filter(&block)
26
- @backtrace_filter = Proc.new if block_given?
27
- @backtrace_filter
28
- end
29
-
30
- # Public: Takes a block and adds it to the list of ignore filters. When
31
- # the filters run, the block will be handed the exception.
32
- #
33
- # &block - The new ignore filter
34
- # If the block returns true the exception will be ignored, otherwise it
35
- # will be processed by honeybadger.
36
- #
37
- # Examples:
38
- #
39
- # config.exception_filter do |exception|
40
- # if exception.class < MyError
41
- # nil
42
- # else
43
- # exception
44
- # end
45
- # end
46
- #
47
- # Yields the the exception data given to Honeybadger.notify
48
- def exception_filter(&block)
49
- @exception_filter = Proc.new if block_given?
50
- @exception_filter
51
- end
52
-
53
- # Public: Generate custom fingerprint (optional)
54
- #
55
- # block - An optional block returning object responding to #to_s
56
- #
57
- # Examples
58
- #
59
- # config.exception_fingerprint do |notice|
60
- # [notice[:error_class], notice[:component], notice[:backtrace].to_s].join(':')
61
- # end
62
- #
63
- # Returns configured fingerprint generator (should respond to #call(notice))
64
- def exception_fingerprint
65
- @exception_fingerprint = Proc.new if block_given?
66
- @exception_fingerprint
67
- end
68
- end
69
- end
70
- end
@@ -1,27 +0,0 @@
1
- require 'honeybadger/plugin'
2
- require 'honeybadger/agent'
3
-
4
- module Honeybadger
5
- module Plugins
6
- module Unicorn
7
- module AfterForkExtension
8
- def self.included(base)
9
- base.send(:alias_method, :init_worker_process_without_honeybadger, :init_worker_process)
10
- base.send(:alias_method, :init_worker_process, :init_worker_process_with_honeybadger)
11
- end
12
-
13
- def init_worker_process_with_honeybadger(*args, &block)
14
- init_worker_process_without_honeybadger(*args, &block).tap do
15
- Honeybadger::Agent.fork
16
- end
17
- end
18
- end
19
-
20
- Plugin.register do
21
- requirement { defined?(::Unicorn::HttpServer) }
22
-
23
- execution { ::Unicorn::HttpServer.send(:include, AfterForkExtension) }
24
- end
25
- end
26
- end
27
- end
@@ -1,16 +0,0 @@
1
- require 'honeybadger'
2
-
3
- module Honeybadger
4
- module Rack
5
- class MetricsReporter
6
- def initialize(app, config)
7
- @app = app
8
- config.logger.warn('DEPRECATION WARNING: `Honeybadger::Rack::MetricsReporter` no longer has any effect and will be removed.')
9
- end
10
-
11
- def call(env)
12
- @app.call(env)
13
- end
14
- end
15
- end
16
- end
@@ -1,55 +0,0 @@
1
- module Honeybadger
2
- module Rack
3
- # Internal: Constructs a request hash from a Rack::Request matching the
4
- # /v1/notices API specification.
5
- class RequestHash < ::Hash
6
- # Internal
7
- CGI_BLACKLIST = ['QUERY_STRING', 'RAW_POST_DATA', 'ORIGINAL_FULLPATH', 'REQUEST_URI'].freeze
8
- CGI_KEY_REGEXP = /\A[A-Z_]+\Z/
9
-
10
- def initialize(request)
11
- self[:url] = extract_url(request)
12
- self[:params] = extract_params(request)
13
- self[:component] = self[:params]['controller']
14
- self[:action] = self[:params]['action']
15
- self[:session] = extract_session(request)
16
- self[:cgi_data] = extract_cgi_data(request)
17
- end
18
-
19
- private
20
-
21
- def extract_url(request)
22
- request.env['honeybadger.request.url'] || request.url
23
- rescue => e
24
- # TODO: Log these errors
25
- "Error: #{e.message}"
26
- end
27
-
28
- def extract_params(request)
29
- (request.env['action_dispatch.request.parameters'] || request.params).to_hash || {}
30
- rescue => e
31
- { error: "Failed to access params -- #{e.message}" }
32
- end
33
-
34
- def extract_session(request)
35
- request.session.to_hash
36
- rescue => e
37
- # Rails raises ArgumentError when `config.secret_token` is missing, and
38
- # ActionDispatch::Session::SessionRestoreError when the session can't be
39
- # restored.
40
- { error: "Failed to access session data -- #{e.message}" }
41
- end
42
-
43
- def extract_cgi_data(request)
44
- request.env.reject {|k,_| cgi_blacklist?(k) }
45
- end
46
-
47
- def cgi_blacklist?(key)
48
- return true if CGI_BLACKLIST.include?(key)
49
- return true unless key.match(CGI_KEY_REGEXP)
50
-
51
- false
52
- end
53
- end
54
- end
55
- end