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.
- 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
|