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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -3
- data/README.md +8 -15
- data/lib/honeybadger.rb +9 -232
- data/lib/honeybadger/agent.rb +292 -134
- data/lib/honeybadger/backend.rb +6 -6
- data/lib/honeybadger/backend/base.rb +11 -0
- data/lib/honeybadger/backend/server.rb +2 -14
- data/lib/honeybadger/cli.rb +0 -2
- data/lib/honeybadger/cli/deploy.rb +42 -0
- data/lib/honeybadger/cli/exec.rb +138 -0
- data/lib/honeybadger/cli/heroku.rb +1 -22
- data/lib/honeybadger/cli/install.rb +74 -0
- data/lib/honeybadger/cli/main.rb +138 -153
- data/lib/honeybadger/cli/notify.rb +66 -0
- data/lib/honeybadger/cli/test.rb +266 -0
- data/lib/honeybadger/config.rb +178 -162
- data/lib/honeybadger/config/defaults.rb +5 -5
- data/lib/honeybadger/config/env.rb +8 -6
- data/lib/honeybadger/config/ruby.rb +100 -0
- data/lib/honeybadger/config/yaml.rb +18 -19
- data/lib/honeybadger/const.rb +3 -16
- data/lib/honeybadger/context_manager.rb +50 -0
- data/lib/honeybadger/init/rails.rb +9 -21
- data/lib/honeybadger/init/rake.rb +2 -0
- data/lib/honeybadger/init/ruby.rb +9 -0
- data/lib/honeybadger/init/sinatra.rb +13 -6
- data/lib/honeybadger/notice.rb +29 -14
- data/lib/honeybadger/plugins/delayed_job/plugin.rb +4 -5
- data/lib/honeybadger/plugins/passenger.rb +1 -2
- data/lib/honeybadger/plugins/rails.rb +0 -28
- data/lib/honeybadger/plugins/resque.rb +2 -5
- data/lib/honeybadger/plugins/shoryuken.rb +2 -2
- data/lib/honeybadger/plugins/sidekiq.rb +2 -2
- data/lib/honeybadger/plugins/sucker_punch.rb +1 -0
- data/lib/honeybadger/plugins/thor.rb +2 -2
- data/lib/honeybadger/plugins/warden.rb +1 -0
- data/lib/honeybadger/rack/error_notifier.rb +11 -9
- data/lib/honeybadger/rack/user_feedback.rb +6 -4
- data/lib/honeybadger/rack/user_informer.rb +6 -4
- data/lib/honeybadger/ruby.rb +2 -0
- data/lib/honeybadger/singleton.rb +26 -0
- data/lib/honeybadger/util/http.rb +12 -0
- data/lib/honeybadger/util/request_hash.rb +71 -0
- data/lib/honeybadger/util/sanitizer.rb +101 -64
- data/lib/honeybadger/version.rb +1 -1
- data/lib/honeybadger/worker.rb +246 -0
- metadata +17 -13
- data/lib/honeybadger/agent/batch.rb +0 -50
- data/lib/honeybadger/agent/null_worker.rb +0 -26
- data/lib/honeybadger/agent/worker.rb +0 -243
- data/lib/honeybadger/cli/helpers.rb +0 -160
- data/lib/honeybadger/config/callbacks.rb +0 -70
- data/lib/honeybadger/plugins/unicorn.rb +0 -27
- data/lib/honeybadger/rack/metrics_reporter.rb +0 -16
- data/lib/honeybadger/rack/request_hash.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66755445d403dbe5c3e653791c8e272a71e0d5a1
|
4
|
+
data.tar.gz: f774d8cfd575862e71cbe0ac72e468e6c3553392
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4b10896f7bb00e2e76a76bdc9d6ae3f1f8dc4c06398f926fb3a7e5685c039c41b99706879b71ae83951d9befe5010f31efb23afb54ed673b811072fee4d1b39
|
7
|
+
data.tar.gz: 37dc725bf41daf0d03ec874d56473b4376c1d7335b3bccc84f7494c822f97d449974920c01f5668be9b1759ccefb4c3739ddeb0382839e23c1449b4173c3a46a
|
data/CHANGELOG.md
CHANGED
@@ -5,9 +5,64 @@ adheres to [Semantic Versioning](http://semver.org/).
|
|
5
5
|
|
6
6
|
## [Unreleased]
|
7
7
|
|
8
|
-
## [
|
9
|
-
###
|
10
|
-
-
|
8
|
+
## [3.0.0] - unreleased
|
9
|
+
### Added
|
10
|
+
- You may now require 'honeybadger/ruby' instead of 'honeybadger' to get the
|
11
|
+
agent without the integrations (no railtie, plugins or monkey patching).
|
12
|
+
- You can now create multiple instances of the Honeybadger agent with different
|
13
|
+
configurations (many classes in the library can be composed).
|
14
|
+
- `Honeybadger.configure` works again -- use it to configure the library from
|
15
|
+
Ruby! (we still default to honeybadger.yml in our installer)
|
16
|
+
- Our test suite is now leaner and meaner (which means we can add new features
|
17
|
+
faster). Reduced typical build times from up to 2 minutes to 20 seconds.
|
18
|
+
- We've rebuilt the CLI from scratch. The new CLI features super verbose error
|
19
|
+
messages with (hopefully) helpful suggestions, some new commands, and better
|
20
|
+
framework detection in the `install` and `test` commands.
|
21
|
+
- Use `honeybadger exec your_command` from the command line to report the error
|
22
|
+
when the command fails due to a non-zero exit status or standard error output.
|
23
|
+
(Use it to report failures in cron!) See `honeybadger help exec`.
|
24
|
+
- Use `honeybadger notify` from the command line to report custom errors to
|
25
|
+
Honeybadger. See `honeybadger help notify`.
|
26
|
+
- ~/honeybadger.yml is now a default config path for the CLI and standalone-ruby
|
27
|
+
installations.
|
28
|
+
- `Honeybadger.notify` now converts arguments which are not `Exception` or
|
29
|
+
`Hash` types to strings and assigns them as the error message. Example:
|
30
|
+
`Honeybadger.notify("Something went wrong")`.
|
31
|
+
|
32
|
+
### Changed
|
33
|
+
- `Honeybadger.start` has been deprecated and has no effect.
|
34
|
+
- We've changed some of the underlying code of the library. If you depend on
|
35
|
+
internal APIs (such as thread local variable names or any functions not marked
|
36
|
+
public in the code comments) then you may need to update your code. If you are
|
37
|
+
developing 3rd-party integrations with our gem [let us
|
38
|
+
know](https://github.com/honeybadger-io/honeybadger-ruby/issues) so that we can
|
39
|
+
work with you to build the public APIs you need.
|
40
|
+
- All Rack middleware no longer require an argument (which used to be a
|
41
|
+
`Honeybadger::Config` instance) when using them. They now default to the
|
42
|
+
global agent and accept an optional argument which expects an alternate
|
43
|
+
`Honeybadger::Agent` instance.
|
44
|
+
- The *plugins.skip* config option has been renamed to *skipped_plugins*.
|
45
|
+
- The *sidekiq.use_component* config option is now `true` by default. To get the
|
46
|
+
old behavior, set it to `false`. When enabled, the Sidekiq plugin will
|
47
|
+
automatically set the component to the class of the job, which helps with
|
48
|
+
grouping.
|
49
|
+
- The `request.filter_keys` option now includes partial matches: with the filter
|
50
|
+
value "password", keys such as "password" and "otherpassword" will be
|
51
|
+
filtered.
|
52
|
+
- CGI variables are now whitelisted when sending the Rack environment to
|
53
|
+
Honeybadger to prevent sensitive data leakage.
|
54
|
+
- `Honeybadger.notify` now raises an exception in development mode when called
|
55
|
+
without the required arguments. It logs outside of development and continues
|
56
|
+
to send a generic error report.
|
57
|
+
|
58
|
+
### Removed
|
59
|
+
- Ruby 1.9.3 and 2.0.x are no longer supported.
|
60
|
+
- `Honeybadger.notify_or_ignore` has been removed. Use `Honeybadger.notify(e)`
|
61
|
+
and `Honeybadger.notify(e, force: true)` (to skip ignore filters).
|
62
|
+
- The CLI command `honeybadger config` has been removed.
|
63
|
+
- All deprecated Rails controller methods (from version 1.x) have been removed.
|
64
|
+
- The deprecated `Honeybadger::Rack::MetricsReporter` middleware has been
|
65
|
+
removed.
|
11
66
|
|
12
67
|
## [2.7.1] - 2016-11-16
|
13
68
|
### Fixed
|
data/README.md
CHANGED
@@ -11,9 +11,8 @@ When an uncaught exception occurs, Honeybadger will POST the relevant data to th
|
|
11
11
|
|
12
12
|
| Ruby Interpreter | Supported Version |
|
13
13
|
| ---- | ---- |
|
14
|
-
| MRI | >= 1.
|
15
|
-
|
|
16
|
-
| Rubinius | >= 2.0 |
|
14
|
+
| MRI | >= 2.1.0 |
|
15
|
+
| Rubinius | >= 2.0 |
|
17
16
|
|
18
17
|
## Supported web frameworks
|
19
18
|
|
@@ -117,26 +116,20 @@ With rack, you have to do things manually, but it's still just a few lines of co
|
|
117
116
|
|
118
117
|
```ruby
|
119
118
|
require 'rack'
|
120
|
-
|
119
|
+
|
121
120
|
# Load the gem
|
122
121
|
require 'honeybadger'
|
123
|
-
|
122
|
+
|
124
123
|
# Write your app
|
125
124
|
app = Rack::Builder.app do
|
126
125
|
run lambda { |env| raise "Rack down" }
|
127
126
|
end
|
128
|
-
|
129
|
-
# Configure and start Honeybadger
|
130
|
-
honeybadger_config = Honeybadger::Config.new(env: ENV['RACK_ENV'])
|
131
|
-
Honeybadger.start(honeybadger_config)
|
132
|
-
|
133
|
-
# And use Honeybadger's rack middleware
|
134
|
-
use Honeybadger::Rack::ErrorNotifier, honeybadger_config
|
135
|
-
|
136
|
-
run app
|
137
|
-
```
|
138
127
|
|
128
|
+
# Use Honeybadger's rack middleware
|
129
|
+
use Honeybadger::Rack::ErrorNotifier
|
139
130
|
|
131
|
+
run app
|
132
|
+
```
|
140
133
|
|
141
134
|
|
142
135
|
## Advanced Configuration
|
data/lib/honeybadger.rb
CHANGED
@@ -1,241 +1,18 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
require 'honeybadger/const'
|
3
|
-
|
4
|
-
module Honeybadger
|
5
|
-
include Forwardable
|
6
|
-
|
7
|
-
extend self
|
8
|
-
|
9
|
-
# Public: Starts the Honeybadger service.
|
10
|
-
#
|
11
|
-
# opts - The Hash options used to initialize Honeybadger. Accepts config
|
12
|
-
# keys in addition to the listed options. Order of precedence for
|
13
|
-
# config is: 1) ENV, 2) config on disk, 3) opts. (default: {})
|
14
|
-
# :logger - An alternate Logger to use. (optional)
|
15
|
-
#
|
16
|
-
# Examples:
|
17
|
-
#
|
18
|
-
# ENV['HONEYBADGER_API_KEY'] # => 'asdf'
|
19
|
-
#
|
20
|
-
# Honeybadger.start # => true
|
21
|
-
#
|
22
|
-
# Honeybadger.start({
|
23
|
-
# :root => ::Rails.root,
|
24
|
-
# :'config.path' => 'config/',
|
25
|
-
# :logger => Honeybadger::Logging::FormattedLogger.new(::Rails.logger)
|
26
|
-
# }) # => true
|
27
|
-
#
|
28
|
-
# Returns true if started, otherwise false.
|
29
|
-
def start(config = {})
|
30
|
-
Agent.start(config)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Public: Stops the Honeybadger service.
|
34
|
-
#
|
35
|
-
# Examples:
|
36
|
-
#
|
37
|
-
# Honeybadger.stop # => nil
|
38
|
-
#
|
39
|
-
# Returns nothing
|
40
|
-
def stop
|
41
|
-
Agent.stop
|
42
|
-
end
|
43
|
-
|
44
|
-
# Public: Send an exception to Honeybadger. Does not report ignored
|
45
|
-
# exceptions by default.
|
46
|
-
#
|
47
|
-
# exception_or_opts - An Exception object, or a Hash of options which is used
|
48
|
-
# to build the notice.
|
49
|
-
# opts - The options Hash when the first argument is an
|
50
|
-
# Exception. (default: {}):
|
51
|
-
# :error_class - The String class name of the error.
|
52
|
-
# :error_message - The String error message.
|
53
|
-
# :force - Always report the exception (even when
|
54
|
-
# ignored).
|
55
|
-
#
|
56
|
-
# Examples:
|
57
|
-
#
|
58
|
-
# # With an exception:
|
59
|
-
# begin
|
60
|
-
# fail 'oops'
|
61
|
-
# rescue => exception
|
62
|
-
# Honeybadger.notify(exception, context: {
|
63
|
-
# my_data: 'value'
|
64
|
-
# }) # => '0dfb92ae-9b01-42e9-9c13-31205b70744a'
|
65
|
-
# end
|
66
|
-
#
|
67
|
-
# # Custom notification:
|
68
|
-
# Honeybadger.notify({
|
69
|
-
# error_class: 'MyClass',
|
70
|
-
# error_message: 'Something went wrong.',
|
71
|
-
# context: {my_data: 'value'}
|
72
|
-
# }) # => '06221c5a-b471-41e5-baeb-de247da45a56'
|
73
|
-
#
|
74
|
-
# Returns a String UUID reference to the notice within Honeybadger or false
|
75
|
-
# when ignored.
|
76
|
-
def notify(exception_or_opts, opts = {})
|
77
|
-
opts.merge!(exception: exception_or_opts) if exception_or_opts.is_a?(Exception)
|
78
|
-
opts.merge!(exception_or_opts.to_hash) if exception_or_opts.respond_to?(:to_hash)
|
79
|
-
Agent.instance ? Agent.instance.notice(opts) : false
|
80
|
-
end
|
81
|
-
|
82
|
-
# Deprecated: Legacy support.
|
83
|
-
alias_method :notify_or_ignore, :notify
|
84
|
-
|
85
|
-
# Public: Callback to ignore exceptions.
|
86
|
-
#
|
87
|
-
# See public API documentation for Honeybadger::Notice for available attributes.
|
88
|
-
#
|
89
|
-
# block - A block returning TrueClass true (to ignore) or FalseClass false
|
90
|
-
# (to send).
|
91
|
-
#
|
92
|
-
# Examples:
|
93
|
-
#
|
94
|
-
# # Ignoring based on error message:
|
95
|
-
# Honeybadger.exception_filter do |notice|
|
96
|
-
# notice[:error_message] =~ /sensitive data/
|
97
|
-
# end
|
98
|
-
#
|
99
|
-
# # Ignore an entire class of exceptions:
|
100
|
-
# Honeybadger.exception_filter do |notice|
|
101
|
-
# notice[:exception].class < MyError
|
102
|
-
# end
|
103
|
-
#
|
104
|
-
# Returns nothing.
|
105
|
-
def exception_filter(&block)
|
106
|
-
Agent.exception_filter(&block)
|
107
|
-
end
|
108
|
-
|
109
|
-
# Public: Callback to add a custom grouping strategy for exceptions. The
|
110
|
-
# return value is hashed and sent to Honeybadger. Errors with the same
|
111
|
-
# fingerprint will be grouped.
|
112
|
-
#
|
113
|
-
# See public API documentation for Honeybadger::Notice for available attributes.
|
114
|
-
#
|
115
|
-
# block - A block returning any Object responding to #to_s.
|
116
|
-
#
|
117
|
-
# Examples:
|
118
|
-
#
|
119
|
-
# Honeybadger.exception_fingerprint do |notice|
|
120
|
-
# [notice[:error_class], notice[:component], notice[:backtrace].to_s].join(':')
|
121
|
-
# end
|
122
|
-
#
|
123
|
-
# Returns nothing.
|
124
|
-
def exception_fingerprint(&block)
|
125
|
-
Agent.exception_fingerprint(&block)
|
126
|
-
end
|
127
|
-
|
128
|
-
# Public: Callback to filter backtrace lines. One use for this is to make
|
129
|
-
# additional [PROJECT_ROOT] or [GEM_ROOT] substitutions, which are used by
|
130
|
-
# Honeybadger when grouping errors and displaying application traces.
|
131
|
-
#
|
132
|
-
# block - A block which can be used to modify the Backtrace lines sent to
|
133
|
-
# Honeybadger. The block expects one argument (line) which is the String line
|
134
|
-
# from the Backtrace, and must return the String new line.
|
135
|
-
#
|
136
|
-
# Examples:
|
137
|
-
#
|
138
|
-
# Honeybadger.backtrace_filter do |line|
|
139
|
-
# line.gsub(/^\/my\/unknown\/bundle\/path/, "[GEM_ROOT]")
|
140
|
-
# end
|
141
|
-
#
|
142
|
-
# Returns nothing.
|
143
|
-
def backtrace_filter(&block)
|
144
|
-
Agent.backtrace_filter(&block)
|
145
|
-
end
|
146
|
-
|
147
|
-
# Public: Save global context for the current request.
|
148
|
-
#
|
149
|
-
# hash - A Hash of data which will be sent to Honeybadger when an error
|
150
|
-
# occurs. (default: nil)
|
151
|
-
#
|
152
|
-
# Examples:
|
153
|
-
#
|
154
|
-
# Honeybadger.context({my_data: 'my value'})
|
155
|
-
#
|
156
|
-
# # Inside a Rails controller:
|
157
|
-
# before_action do
|
158
|
-
# Honeybadger.context({user_id: current_user.id})
|
159
|
-
# end
|
160
|
-
#
|
161
|
-
# # Clearing global context:
|
162
|
-
# Honeybadger.context.clear!
|
163
|
-
#
|
164
|
-
# Returns self so that method calls can be chained.
|
165
|
-
def context(hash = nil)
|
166
|
-
unless hash.nil?
|
167
|
-
Thread.current[:__honeybadger_context] ||= {}
|
168
|
-
Thread.current[:__honeybadger_context].merge!(hash)
|
169
|
-
end
|
170
|
-
|
171
|
-
self
|
172
|
-
end
|
173
|
-
|
174
|
-
|
175
|
-
# Public: Get global context for the current request.
|
176
|
-
#
|
177
|
-
#
|
178
|
-
# Examples:
|
179
|
-
#
|
180
|
-
# Honeybadger.context({my_data: 'my value'})
|
181
|
-
# Honeybadger.get_context #now returns {my_data: 'my value'}
|
182
|
-
#
|
183
|
-
# Returns hash or nil.
|
184
|
-
def get_context
|
185
|
-
Thread.current[:__honeybadger_context]
|
186
|
-
end
|
187
|
-
|
188
|
-
# Internal: Clears the global context
|
189
|
-
def clear!
|
190
|
-
Thread.current[:__honeybadger_context] = nil
|
191
|
-
end
|
192
|
-
|
193
|
-
# Public: Flushes all data from workers before returning. This is most useful
|
194
|
-
# in tests when using the test backend, where normally the asynchronous
|
195
|
-
# nature of this library could create race conditions.
|
196
|
-
#
|
197
|
-
# block - The optional block to execute (exceptions will propagate after data
|
198
|
-
# is flushed).
|
199
|
-
#
|
200
|
-
# Examples:
|
201
|
-
#
|
202
|
-
# # Without a block:
|
203
|
-
# it "sends a notification to Honeybadger" do
|
204
|
-
# expect {
|
205
|
-
# Honeybadger.notify(StandardError.new('test backend'))
|
206
|
-
# Honeybadger.flush
|
207
|
-
# }.to change(Honeybadger::Backend::Test.notifications[:notices], :size).by(1)
|
208
|
-
# end
|
209
|
-
#
|
210
|
-
# # With a block:
|
211
|
-
# it "sends a notification to Honeybadger" do
|
212
|
-
# expect {
|
213
|
-
# Honeybadger.flush do
|
214
|
-
# 50.times do
|
215
|
-
# Honeybadger.notify(StandardError.new('test backend'))
|
216
|
-
# end
|
217
|
-
# end
|
218
|
-
# }.to change(Honeybadger::Backend::Test.notifications[:notices], :size).by(50)
|
219
|
-
# end
|
220
|
-
#
|
221
|
-
# Returns value of block if block is given, otherwise true on success or
|
222
|
-
# false if Honeybadger isn't running.
|
223
|
-
def flush(&block)
|
224
|
-
Agent.flush(&block)
|
225
|
-
end
|
226
|
-
|
227
|
-
def configure(*args)
|
228
|
-
warn('UPGRADE WARNING: Honeybadger.configure was removed in v2.0 and has no effect. Please upgrade: https://www.honeybadger.io/s/gem-upgrade')
|
229
|
-
nil
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
1
|
if defined?(::Rails::Railtie)
|
234
2
|
require 'honeybadger/init/rails'
|
235
3
|
elsif defined?(Sinatra::Base)
|
236
4
|
require 'honeybadger/init/sinatra'
|
5
|
+
else
|
6
|
+
require 'honeybadger/init/ruby'
|
237
7
|
end
|
238
8
|
|
239
9
|
if defined?(Rake.application)
|
240
10
|
require 'honeybadger/init/rake'
|
241
11
|
end
|
12
|
+
|
13
|
+
at_exit do
|
14
|
+
if $! && !$!.is_a?(SystemExit) && Honeybadger.config[:'exceptions.notify_at_exit']
|
15
|
+
Honeybadger.notify($!, component: 'at_exit', sync: true)
|
16
|
+
end
|
17
|
+
Honeybadger.stop if Honeybadger.config[:'send_data_at_exit']
|
18
|
+
end
|
data/lib/honeybadger/agent.rb
CHANGED
@@ -2,204 +2,362 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
require 'honeybadger/version'
|
4
4
|
require 'honeybadger/config'
|
5
|
+
require 'honeybadger/context_manager'
|
5
6
|
require 'honeybadger/notice'
|
6
7
|
require 'honeybadger/plugin'
|
7
8
|
require 'honeybadger/logging'
|
9
|
+
require 'honeybadger/worker'
|
8
10
|
|
9
11
|
module Honeybadger
|
10
|
-
#
|
12
|
+
# Public: The Honeybadger agent contains all the methods for interacting with
|
13
|
+
# the Honeybadger service. It can be used to send notifications to multiple
|
14
|
+
# projects in large apps.
|
15
|
+
#
|
16
|
+
# Context is global by default, meaning agents created via
|
17
|
+
# `Honeybadger::Agent.new` will share context (added via
|
18
|
+
# `Honeybadger.context` or `Honeybadger::Agent#context`) with other agents.
|
19
|
+
# This also includes the Rack environment when using the Honeybadger rack
|
20
|
+
# middleware.
|
21
|
+
#
|
22
|
+
# Examples:
|
23
|
+
#
|
24
|
+
# # Standard usage:
|
25
|
+
# OtherBadger = Honeybadger::Agent.new
|
26
|
+
#
|
27
|
+
# # With local context:
|
28
|
+
# OtherBadger = Honeybadger::Agent.new(local_context: true)
|
29
|
+
#
|
30
|
+
# OtherBadger.configure do |config|
|
31
|
+
# config.api_key = 'project api key'
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# begin
|
35
|
+
# # Risky operation
|
36
|
+
# rescue => e
|
37
|
+
# OtherBadger.notify(e)
|
38
|
+
# end
|
11
39
|
class Agent
|
12
40
|
extend Forwardable
|
13
41
|
|
14
42
|
include Logging::Helper
|
15
43
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
class << self
|
20
|
-
extend Forwardable
|
44
|
+
def self.instance
|
45
|
+
@instance
|
46
|
+
end
|
21
47
|
|
22
|
-
|
48
|
+
def self.instance=(instance)
|
49
|
+
@instance = instance
|
50
|
+
end
|
23
51
|
|
24
|
-
|
25
|
-
|
52
|
+
def initialize(opts = {})
|
53
|
+
if opts.kind_of?(Config)
|
54
|
+
@config = opts
|
55
|
+
opts = {}
|
26
56
|
end
|
27
|
-
end
|
28
57
|
|
29
|
-
|
58
|
+
@context = opts.delete(:context)
|
59
|
+
@context ||= ContextManager.new if opts.delete(:local_context)
|
30
60
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
Plugin.load!(config)
|
61
|
+
@config ||= Config.new(opts)
|
62
|
+
|
63
|
+
init_worker
|
36
64
|
end
|
37
65
|
|
38
|
-
|
66
|
+
# Public: Send an exception to Honeybadger. Does not report ignored
|
67
|
+
# exceptions by default.
|
68
|
+
#
|
69
|
+
# exception_or_opts - An Exception object, or a Hash of options which is used
|
70
|
+
# to build the notice. All other types of objects will
|
71
|
+
# be converted to a String and used as the `:error_message`.
|
72
|
+
# opts - The options Hash when the first argument is an
|
73
|
+
# Exception. (default: {}):
|
74
|
+
# :error_message - The String error message.
|
75
|
+
# :error_class - The String class name of the error. (optional)
|
76
|
+
# :force - Always report the exception, even when
|
77
|
+
# ignored. (optional)
|
78
|
+
#
|
79
|
+
# Examples:
|
80
|
+
#
|
81
|
+
# # With an exception:
|
82
|
+
# begin
|
83
|
+
# fail 'oops'
|
84
|
+
# rescue => exception
|
85
|
+
# Honeybadger.notify(exception, context: {
|
86
|
+
# my_data: 'value'
|
87
|
+
# }) # => '-1dfb92ae-9b01-42e9-9c13-31205b70744a'
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# # Custom notification:
|
91
|
+
# Honeybadger.notify({
|
92
|
+
# error_class: 'MyClass',
|
93
|
+
# error_message: 'Something went wrong.',
|
94
|
+
# context: {my_data: 'value'}
|
95
|
+
# }) # => '06220c5a-b471-41e5-baeb-de247da45a56'
|
96
|
+
#
|
97
|
+
# Returns a String UUID reference to the notice within Honeybadger or false
|
98
|
+
# when ignored.
|
99
|
+
def notify(exception_or_opts, opts = {})
|
100
|
+
return false if config.disabled?
|
101
|
+
|
102
|
+
if exception_or_opts.is_a?(Exception)
|
103
|
+
opts.merge!(exception: exception_or_opts)
|
104
|
+
elsif exception_or_opts.respond_to?(:to_hash)
|
105
|
+
opts.merge!(exception_or_opts.to_hash)
|
106
|
+
else
|
107
|
+
opts[:error_message] = exception_or_opts.to_s
|
108
|
+
end
|
39
109
|
|
40
|
-
|
41
|
-
@instance
|
42
|
-
end
|
110
|
+
validate_notify_opts!(opts)
|
43
111
|
|
44
|
-
|
45
|
-
!
|
46
|
-
end
|
112
|
+
opts.merge!(rack_env: context_manager.get_rack_env)
|
113
|
+
opts.merge!(global_context: context_manager.get_context)
|
47
114
|
|
48
|
-
|
49
|
-
return true if running?
|
115
|
+
notice = Notice.new(config, opts)
|
50
116
|
|
51
|
-
unless
|
52
|
-
|
117
|
+
unless notice.api_key =~ NOT_BLANK
|
118
|
+
error { sprintf('Unable to send error report: API key is missing. id=%s', notice.id) }
|
119
|
+
return false
|
53
120
|
end
|
54
121
|
|
55
|
-
if
|
56
|
-
|
57
|
-
return false
|
58
|
-
elsif !config.valid?
|
59
|
-
config.logger.warn('Unable to start Honeybadger -- api_key is missing or invalid.')
|
122
|
+
if !opts[:force] && notice.ignore?
|
123
|
+
debug { sprintf('ignore notice feature=notices id=%s', notice.id) }
|
60
124
|
return false
|
61
125
|
end
|
62
126
|
|
63
|
-
|
64
|
-
config.logger.warn('Failed to connect to Honeybadger service -- please verify that api.honeybadger.io is reachable (connection will be retried).')
|
65
|
-
end
|
127
|
+
info { sprintf('Reporting error id=%s', notice.id) }
|
66
128
|
|
67
|
-
|
68
|
-
|
69
|
-
|
129
|
+
if opts[:sync]
|
130
|
+
send_now(notice)
|
131
|
+
else
|
132
|
+
push(notice)
|
133
|
+
end
|
70
134
|
|
71
|
-
|
135
|
+
notice.id
|
72
136
|
end
|
73
137
|
|
74
|
-
|
75
|
-
|
76
|
-
|
138
|
+
# Public: Save global context for the current request.
|
139
|
+
#
|
140
|
+
# hash - A Hash of data which will be sent to Honeybadger when an error
|
141
|
+
# occurs. (default: nil)
|
142
|
+
#
|
143
|
+
# Examples:
|
144
|
+
#
|
145
|
+
# Honeybadger.context({my_data: 'my value'})
|
146
|
+
#
|
147
|
+
# # Inside a Rails controller:
|
148
|
+
# before_action do
|
149
|
+
# Honeybadger.context({user_id: current_user.id})
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# # Clearing global context:
|
153
|
+
# Honeybadger.context.clear!
|
154
|
+
#
|
155
|
+
# Returns self so that method calls can be chained.
|
156
|
+
def context(hash = nil)
|
157
|
+
context_manager.set_context(hash) unless hash.nil?
|
158
|
+
self
|
77
159
|
end
|
78
160
|
|
79
|
-
|
80
|
-
|
161
|
+
# Internal: Used to clear context via `#context.clear!`.
|
162
|
+
def clear!
|
163
|
+
context_manager.clear!
|
81
164
|
end
|
82
165
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
166
|
+
# Public: Get global context for the current request.
|
167
|
+
#
|
168
|
+
#
|
169
|
+
# Examples:
|
170
|
+
#
|
171
|
+
# Honeybadger.context({my_data: 'my value'})
|
172
|
+
# Honeybadger.get_context #now returns {my_data: 'my value'}
|
173
|
+
#
|
174
|
+
# Returns hash or nil.
|
175
|
+
def get_context
|
176
|
+
context_manager.get_context
|
91
177
|
end
|
92
178
|
|
93
|
-
#
|
179
|
+
# Public: Flushes all data from workers before returning. This is most useful
|
180
|
+
# in tests when using the test backend, where normally the asynchronous
|
181
|
+
# nature of this library could create race conditions.
|
182
|
+
#
|
183
|
+
# block - The optional block to execute (exceptions will propagate after data
|
184
|
+
# is flushed).
|
185
|
+
#
|
186
|
+
# Examples:
|
187
|
+
#
|
188
|
+
# # Without a block:
|
189
|
+
# it "sends a notification to Honeybadger" do
|
190
|
+
# expect {
|
191
|
+
# Honeybadger.notify(StandardError.new('test backend'))
|
192
|
+
# Honeybadger.flush
|
193
|
+
# }.to change(Honeybadger::Backend::Test.notifications[:notices], :size).by(0)
|
194
|
+
# end
|
94
195
|
#
|
95
|
-
#
|
196
|
+
# # With a block:
|
197
|
+
# it "sends a notification to Honeybadger" do
|
198
|
+
# expect {
|
199
|
+
# Honeybadger.flush do
|
200
|
+
# 49.times do
|
201
|
+
# Honeybadger.notify(StandardError.new('test backend'))
|
202
|
+
# end
|
203
|
+
# end
|
204
|
+
# }.to change(Honeybadger::Backend::Test.notifications[:notices], :size).by(49)
|
205
|
+
# end
|
96
206
|
#
|
97
|
-
# Returns
|
98
|
-
|
99
|
-
|
100
|
-
|
207
|
+
# Returns value of block if block is given, otherwise true on success or
|
208
|
+
# false if Honeybadger isn't running.
|
209
|
+
def flush
|
210
|
+
return true unless block_given?
|
211
|
+
yield
|
212
|
+
ensure
|
213
|
+
worker.flush
|
101
214
|
end
|
102
215
|
|
103
|
-
#
|
216
|
+
# Public: Stops the Honeybadger service.
|
104
217
|
#
|
105
|
-
#
|
106
|
-
# cases (such as the delayed_job plugin) necessitate it.
|
218
|
+
# Examples:
|
107
219
|
#
|
108
|
-
#
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
end
|
220
|
+
# Honeybadger.stop # => nil
|
221
|
+
#
|
222
|
+
# Returns nothing
|
223
|
+
def stop(force = false)
|
224
|
+
worker.send(force ? :shutdown! : :shutdown)
|
225
|
+
true
|
115
226
|
end
|
116
227
|
|
117
|
-
attr_reader :
|
228
|
+
attr_reader :config
|
118
229
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
notify_at_exit($!)
|
136
|
-
stop if config[:'send_data_at_exit']
|
137
|
-
self.class.at_exit.call if self.class.at_exit
|
138
|
-
|
139
|
-
exit(exit_status) if exit_status
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def stop(force = false)
|
144
|
-
workers.each_pair do |key, worker|
|
145
|
-
worker.send(force ? :shutdown! : :shutdown)
|
146
|
-
end
|
230
|
+
# Public: Configure the Honeybadger agent via Ruby.
|
231
|
+
#
|
232
|
+
# block - The configuration block.
|
233
|
+
#
|
234
|
+
# Examples:
|
235
|
+
#
|
236
|
+
# Honeybadger.configure do |config|
|
237
|
+
# config.api_key = 'project api key'
|
238
|
+
# config.exceptions.ignore += [CustomError]
|
239
|
+
# end
|
240
|
+
#
|
241
|
+
# Yields configuration object.
|
242
|
+
# Returns nothing.
|
243
|
+
def_delegator :config, :configure
|
147
244
|
|
148
|
-
|
149
|
-
|
245
|
+
# Public: Callback to ignore exceptions.
|
246
|
+
#
|
247
|
+
# See public API documentation for Honeybadger::Notice for available attributes.
|
248
|
+
#
|
249
|
+
# block - A block returning TrueClass true (to ignore) or FalseClass false
|
250
|
+
# (to send).
|
251
|
+
#
|
252
|
+
# Examples:
|
253
|
+
#
|
254
|
+
# # Ignoring based on error message:
|
255
|
+
# Honeybadger.exception_filter do |notice|
|
256
|
+
# notice[:error_message] =~ /sensitive data/
|
257
|
+
# end
|
258
|
+
#
|
259
|
+
# # Ignore an entire class of exceptions:
|
260
|
+
# Honeybadger.exception_filter do |notice|
|
261
|
+
# notice[:exception].class < MyError
|
262
|
+
# end
|
263
|
+
#
|
264
|
+
# Returns nothing.
|
265
|
+
def_delegator :config, :exception_filter
|
150
266
|
|
151
|
-
|
152
|
-
|
153
|
-
|
267
|
+
# Public: Callback to add a custom grouping strategy for exceptions. The
|
268
|
+
# return value is hashed and sent to Honeybadger. Errors with the same
|
269
|
+
# fingerprint will be grouped.
|
270
|
+
#
|
271
|
+
# See public API documentation for Honeybadger::Notice for available attributes.
|
272
|
+
#
|
273
|
+
# block - A block returning any Object responding to #to_s.
|
274
|
+
#
|
275
|
+
# Examples:
|
276
|
+
#
|
277
|
+
# Honeybadger.exception_fingerprint do |notice|
|
278
|
+
# [notice[:error_class], notice[:component], notice[:backtrace].to_s].join(':')
|
279
|
+
# end
|
280
|
+
#
|
281
|
+
# Returns nothing.
|
282
|
+
def_delegator :config, :exception_fingerprint
|
154
283
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
284
|
+
# Public: Callback to filter backtrace lines. One use for this is to make
|
285
|
+
# additional [PROJECT_ROOT] or [GEM_ROOT] substitutions, which are used by
|
286
|
+
# Honeybadger when grouping errors and displaying application traces.
|
287
|
+
#
|
288
|
+
# block - A block which can be used to modify the Backtrace lines sent to
|
289
|
+
# Honeybadger. The block expects one argument (line) which is the String line
|
290
|
+
# from the Backtrace, and must return the String new line.
|
291
|
+
#
|
292
|
+
# Examples:
|
293
|
+
#
|
294
|
+
# Honeybadger.backtrace_filter do |line|
|
295
|
+
# line.gsub(/^\/my\/unknown\/bundle\/path/, "[GEM_ROOT]")
|
296
|
+
# end
|
297
|
+
#
|
298
|
+
# Returns nothing.
|
299
|
+
def_delegator :config, :backtrace_filter
|
164
300
|
|
165
|
-
#
|
301
|
+
# Public: Sets the Rack environment which is used to report request data
|
302
|
+
# with errors.
|
166
303
|
#
|
167
|
-
#
|
304
|
+
# rack_env - The Hash Rack environment.
|
305
|
+
# block - A block to call. Errors reported from within the block will
|
306
|
+
# include request data.
|
168
307
|
#
|
169
|
-
#
|
170
|
-
|
171
|
-
|
308
|
+
# Examples:
|
309
|
+
#
|
310
|
+
# Honeybadger.with_rack_env(env) do
|
311
|
+
# begin
|
312
|
+
# # Risky operation
|
313
|
+
# rescue => e
|
314
|
+
# Honeybadger.notify(e)
|
315
|
+
# end
|
316
|
+
# end
|
317
|
+
#
|
318
|
+
# Returns the return value of block.
|
319
|
+
def with_rack_env(rack_env, &block)
|
320
|
+
context_manager.set_rack_env(rack_env)
|
172
321
|
yield
|
173
322
|
ensure
|
174
|
-
|
323
|
+
context_manager.set_rack_env(nil)
|
175
324
|
end
|
176
325
|
|
177
|
-
|
326
|
+
# Internal
|
327
|
+
attr_reader :worker
|
178
328
|
|
179
|
-
|
329
|
+
# Internal
|
330
|
+
def_delegators :config, :init!
|
180
331
|
|
181
|
-
|
182
|
-
unless config.feature?(feature)
|
183
|
-
debug { sprintf('agent dropping feature=%s reason=ping', feature) }
|
184
|
-
return false
|
185
|
-
end
|
332
|
+
private
|
186
333
|
|
187
|
-
|
334
|
+
def validate_notify_opts!(opts)
|
335
|
+
return if opts.has_key?(:exception)
|
336
|
+
return if opts.has_key?(:error_message)
|
337
|
+
msg = sprintf('`Honeybadger.notify` was called with invalid arguments. You must pass either an Exception or options Hash containing the `:error_message` key. location=%s', caller[caller.size-1])
|
338
|
+
raise ArgumentError.new(msg) if config.dev?
|
339
|
+
warn(msg)
|
340
|
+
end
|
188
341
|
|
189
|
-
|
342
|
+
def context_manager
|
343
|
+
return @context if @context
|
344
|
+
ContextManager.current
|
190
345
|
end
|
191
346
|
|
192
|
-
def
|
193
|
-
|
194
|
-
|
347
|
+
def push(object)
|
348
|
+
worker.push(object)
|
349
|
+
true
|
195
350
|
end
|
196
351
|
|
197
|
-
def
|
198
|
-
|
199
|
-
|
200
|
-
|
352
|
+
def send_now(object)
|
353
|
+
worker.send_now(object)
|
354
|
+
true
|
355
|
+
end
|
201
356
|
|
202
|
-
|
357
|
+
def init_worker
|
358
|
+
@worker = Worker.new(config)
|
203
359
|
end
|
360
|
+
|
361
|
+
@instance = new(Config.new)
|
204
362
|
end
|
205
363
|
end
|