honeybadger 2.7.2 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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