exception_handling 2.15.0 → 2.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14ca7f66e702ec2ae46aa9f7b7669cd8f8136b9305c0683b76339faafc87558a
4
- data.tar.gz: db7863d32347f5f859971222f2b215b0f84a8c7604eb0326cfd9b656910cd9ff
3
+ metadata.gz: 71ab070f1ab59f2f12838fb7d123fa541a71a8bb42fe0d057f06acb015bf32a2
4
+ data.tar.gz: 1c268f42c4a302c88b98411890db5a4870d31bb96ca712e0f6463ba6629f188a
5
5
  SHA512:
6
- metadata.gz: 3274bf4d7f67fb83aa2d71633572d19c14c99e3c40746de20e20efea1ff570a0d49f5163efd74c60ce0167af3495ad259d2950bc198c28a219ff6b30dadf551b
7
- data.tar.gz: 858ce36039ecfbd5a79a22c0a56f9accff534e7b7e27e288509ffd9d34feca3ccd0983a092f6d536e554dce8d4312cb877df5f3a6729305aed8828ed0fe36d8a
6
+ metadata.gz: f571e8c9dd62c70eba4b01c917af6c4715e3d4750900fec8ad7e4a3d5c67fc30ddc299c1456b48adef17c74a3860769806fd0df4e410cb5180c3f778e58c1aad
7
+ data.tar.gz: 98f1596f0a95e1591a768b23574c76e4b4039b54a7bb95f07b4f6d41d40336bae360b7ce76750cc5fec7d9c1a64c78ffc4c72d15b88b4924734bab228bb30c94
@@ -34,7 +34,7 @@ jobs:
34
34
  - uses: ruby/setup-ruby@v1
35
35
  with:
36
36
  ruby-version: ${{ matrix.ruby }}
37
- bundler: 2.2.29
37
+ bundler: 2.3.26
38
38
  bundler-cache: true
39
39
  - name: Unit tests
40
40
  run: bundle exec rspec
data/CHANGELOG.md CHANGED
@@ -4,6 +4,10 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
4
4
 
5
5
  **Note:** this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.16.0] - 2023-05-01
8
+ ### Added
9
+ - Add interface for automatically adding honeybadger tags `ExceptionHandling.honeybadger_auto_tagger=`
10
+
7
11
  ## [2.15.0] - 2023-03-07
8
12
  ### Added
9
13
  - Added support for ActionMailer 7.x
@@ -109,6 +113,7 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
109
113
  ### Changed
110
114
  - No longer depends on hobo_support. Uses invoca-utils 0.3 instead.
111
115
 
116
+ [2.16.0]: https://github.com/Invoca/exception_handling/compare/v2.15.0...v2.16.0
112
117
  [2.15.0]: https://github.com/Invoca/exception_handling/compare/v2.14.0...v2.15.0
113
118
  [2.14.0]: https://github.com/Invoca/exception_handling/compare/v2.13.0...v2.14.0
114
119
  [2.13.0]: https://github.com/Invoca/exception_handling/compare/v2.12.0...v2.13.0
data/Gemfile CHANGED
@@ -4,6 +4,9 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
+ gem 'actionmailer', '~> 6.0'
8
+ gem 'actionpack', '~> 6.0'
9
+ gem 'activesupport', '~> 6.0'
7
10
  gem 'appraisal', '~> 2.2'
8
11
  gem 'honeybadger', '~> 4.11'
9
12
  gem 'pry'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- exception_handling (2.15.0)
4
+ exception_handling (2.16.0)
5
5
  actionmailer (>= 5.2)
6
6
  actionpack (>= 5.2)
7
7
  activesupport (>= 5.2)
@@ -144,6 +144,9 @@ PLATFORMS
144
144
  ruby
145
145
 
146
146
  DEPENDENCIES
147
+ actionmailer (~> 6.0)
148
+ actionpack (~> 6.0)
149
+ activesupport (~> 6.0)
147
150
  appraisal (~> 2.2)
148
151
  exception_handling!
149
152
  honeybadger (~> 4.11)
@@ -156,4 +159,4 @@ DEPENDENCIES
156
159
  test-unit
157
160
 
158
161
  BUNDLED WITH
159
- 2.2.29
162
+ 2.3.22
data/README.md CHANGED
@@ -25,24 +25,26 @@ Or install it yourself as:
25
25
  Add some code to initialize the settings in your application.
26
26
  For example:
27
27
 
28
- require "exception_handling"
29
-
30
- # required
31
- ExceptionHandling.server_name = Cluster['server_name']
32
- ExceptionHandling.sender_address = %("Exceptions" <exceptions@example.com>)
33
- ExceptionHandling.exception_recipients = ['exceptions@example.com']
34
- ExceptionHandling.logger = Rails.logger
35
-
36
- # optional
37
- ExceptionHandling.escalation_recipients = ['escalation@example.com']
38
- ExceptionHandling.filter_list_filename = "#{Rails.root}/config/exception_filters.yml"
39
- ExceptionHandling.email_environment = Rails.env
40
- ExceptionHandling.eventmachine_safe = false
41
- ExceptionHandling.eventmachine_synchrony = false
42
- ExceptionHandling.sensu_host = "127.0.0.1"
43
- ExceptionHandling.sensu_port = 3030
44
- ExceptionHandling.sensu_prefix = ""
45
-
28
+ ```ruby
29
+ require "exception_handling"
30
+
31
+ # required
32
+ ExceptionHandling.server_name = Cluster['server_name']
33
+ ExceptionHandling.sender_address = %("Exceptions" <exceptions@example.com>)
34
+ ExceptionHandling.exception_recipients = ['exceptions@example.com']
35
+ ExceptionHandling.logger = Rails.logger
36
+
37
+ # optional
38
+ ExceptionHandling.escalation_recipients = ['escalation@example.com']
39
+ ExceptionHandling.filter_list_filename = "#{Rails.root}/config/exception_filters.yml"
40
+ ExceptionHandling.email_environment = Rails.env
41
+ ExceptionHandling.eventmachine_safe = false
42
+ ExceptionHandling.eventmachine_synchrony = false
43
+ ExceptionHandling.sensu_host = "127.0.0.1"
44
+ ExceptionHandling.sensu_port = 3030
45
+ ExceptionHandling.sensu_prefix = ""
46
+ ExceptionHandling.honeybadger_auto_tagger = ->(exception) { [] } # See "Automatically Tagging Exceptions" section below for examples
47
+ ```
46
48
 
47
49
  ## Usage
48
50
 
@@ -62,6 +64,40 @@ Then call any method available in the `ExceptionHandling::Methods` mixin:
62
64
  flash.now['error'] = "A specific error occurred. Support has been notified."
63
65
  end
64
66
 
67
+ ### Tagging Exceptions in Honeybadger
68
+
69
+ ⚠️ Honeybadger differentiates tags by spaces and/or commas, so you should **not** include spaces or commas in your tags.
70
+
71
+ ⚠️ Tags are case-sensitive.
72
+
73
+ #### Manually Tagging Exceptions
74
+
75
+ Add `:honeybadger_tags` to your `log_context` usage with an array of strings.
76
+
77
+ ```ruby
78
+ log_error(ex, "A specific error occurred.", honeybadger_tags: ["critical", "sequoia"])
79
+ ```
80
+
81
+ **Note**: Manual tags will be merged with any automatic tags.
82
+
83
+ #### Automatically Tagging Exceptions (`honeybadger_auto_tagger=`)
84
+
85
+ Configure exception handling so that you can automatically apply multiple tags to exceptions sent to honeybadger.
86
+
87
+ The Proc must accept an `exception` argument that will be the exception in question and must always return an array of strings (the array can be empty).
88
+
89
+ Example to enable auto-tagging:
90
+ ```ruby
91
+ ExceptionHandling.honeybadger_auto_tagger = ->(exception) do
92
+ exception.message.match?(/fire/) ? ["high-urgency", "danger"] : ["low-urgency"]
93
+ end
94
+ ```
95
+
96
+ Example to disable auto-tagging:
97
+ ```ruby
98
+ ExceptionHandling.honeybadger_auto_tagger = nil
99
+ ```
100
+
65
101
  ## Custom Hooks
66
102
 
67
103
  ### custom_data_hook
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExceptionHandling
4
- VERSION = '2.15.0'
4
+ VERSION = '2.16.0'
5
5
  end
@@ -114,6 +114,7 @@ module ExceptionHandling # never included
114
114
  attr_reader :filter_list_filename
115
115
  attr_reader :eventmachine_safe
116
116
  attr_reader :eventmachine_synchrony
117
+ attr_reader :honeybadger_auto_tagger
117
118
 
118
119
  @filter_list_filename = "./config/exception_filters.yml"
119
120
  @email_environment = ""
@@ -154,6 +155,14 @@ module ExceptionHandling # never included
154
155
  @exception_catalog ||= ExceptionCatalog.new(@filter_list_filename)
155
156
  end
156
157
 
158
+ # rubocop:disable Style/TrivialAccessors
159
+ # @param value [Proc|nil] Proc that accepts 1 parameter that will be the exception object or nil to disable the auto-tagger.
160
+ # The proc is always expected to return an array of strings. The array can be empty.
161
+ def honeybadger_auto_tagger=(value)
162
+ @honeybadger_auto_tagger = value
163
+ end
164
+ # rubocop:enable Style/TrivialAccessors
165
+
157
166
  #
158
167
  # internal settings (don't set directly)
159
168
  #
@@ -270,9 +279,10 @@ module ExceptionHandling # never included
270
279
  def send_exception_to_honeybadger(exception_info)
271
280
  exception = exception_info.exception
272
281
  exception_description = exception_info.exception_description
282
+
273
283
  # Note: Both commas and spaces are treated as delimiters for the :tags string. Space-delimiters are not officially documented.
274
284
  # https://github.com/honeybadger-io/honeybadger-ruby/pull/422
275
- tags = exception_info.honeybadger_tags.join(' ')
285
+ tags = (honeybadger_auto_tags(exception) + exception_info.honeybadger_tags).join(' ')
276
286
  response = Honeybadger.notify(error_class: exception_description ? exception_description.filter_name : exception.class.name,
277
287
  error_message: exception.message.to_s,
278
288
  exception: exception,
@@ -286,6 +296,18 @@ module ExceptionHandling # never included
286
296
  :failure
287
297
  end
288
298
 
299
+ # @param exception [Exception]
300
+ #
301
+ # @return [Array<String>]
302
+ def honeybadger_auto_tags(exception)
303
+ @honeybadger_auto_tagger&.call(exception) || []
304
+ rescue => ex
305
+ traces = ex.backtrace.join("\n")
306
+ message = "Unable to execute honeybadger_auto_tags callback. #{ExceptionHandling.encode_utf8(ex.message.to_s)} #{traces}\n"
307
+ ExceptionHandling.log_info(message)
308
+ []
309
+ end
310
+
289
311
  #
290
312
  # Check if Honeybadger defined.
291
313
  #
@@ -107,6 +107,11 @@ describe ExceptionHandling do
107
107
  class SmtpClientErrbackStub < SmtpClientStub
108
108
  end
109
109
 
110
+ before(:each) do
111
+ # Reset this for every test since they are applied to the class
112
+ ExceptionHandling.honeybadger_auto_tagger = nil
113
+ end
114
+
110
115
  context "with warn and honeybadger notify stubbed" do
111
116
  before do
112
117
  allow(ExceptionHandling).to receive(:warn).with(any_args)
@@ -149,6 +154,14 @@ describe ExceptionHandling do
149
154
  expect(service_name: 'exception_handling').to eq(logged_excluding_reload_filter.last[:context])
150
155
  end
151
156
 
157
+ it "passes :honeybadger_tags in log context to honeybadger" do
158
+ expect(Honeybadger).to receive(:notify).with(hash_including({ tags: " , awesome , totallytubular, " }))
159
+ ExceptionHandling.log_error('This is an Error', 'This is the prefix context', honeybadger_tags: ' , awesome , totallytubular, ')
160
+
161
+ expect(Honeybadger).to receive(:notify).with(hash_including({ tags: " cool neat" }))
162
+ ExceptionHandling.log_error('This is an Error', 'This is the prefix context', honeybadger_tags: [" ", " cool ", "neat"])
163
+ end
164
+
152
165
  it "logs with Severity::FATAL" do
153
166
  ExceptionHandling.log_error('This is a Warning', service_name: 'exception_handling')
154
167
  expect('FATAL').to eq(logged_excluding_reload_filter.last[:severity])
@@ -1245,6 +1258,53 @@ describe ExceptionHandling do
1245
1258
  expect(logged_excluding_reload_filter.size).to eq(3)
1246
1259
  end
1247
1260
  end
1261
+
1262
+ context "#honeybadger_auto_tagger=" do
1263
+ context "with proc that runs successfully" do
1264
+ before do
1265
+ ExceptionHandling.honeybadger_auto_tagger =
1266
+ ->(exception) do
1267
+ if exception.message =~ /donuts/
1268
+ ['donut-error', 'high-urgency']
1269
+ else
1270
+ ['low-urgency']
1271
+ end
1272
+ end
1273
+ end
1274
+
1275
+ context "without manually passed tags" do
1276
+ let(:exception) { StandardError.new("We are out of chocolate milk") }
1277
+
1278
+ it "adds tags from autotagger" do
1279
+ expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "low-urgency" }))
1280
+ ExceptionHandling.log_error(exception, nil)
1281
+ end
1282
+ end
1283
+
1284
+ context "with manually passed tags" do
1285
+ let(:exception) { StandardError.new("The donuts are burning") }
1286
+
1287
+ it "merges tags from autotagger with manually passed tags" do
1288
+ expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "donut-error high-urgency upset-customers" }))
1289
+ ExceptionHandling.log_error(exception, nil, honeybadger_tags: ["upset-customers"])
1290
+ end
1291
+ end
1292
+ end
1293
+ end
1294
+
1295
+ context "with proc that raises an exception" do
1296
+ let(:exception) { StandardError.new("Something else occurred") }
1297
+
1298
+ before do
1299
+ ExceptionHandling.honeybadger_auto_tagger = ->(_exception) { raise StandardError, "boom" }
1300
+ end
1301
+
1302
+ it "logs a message and returns [] for the tags" do
1303
+ expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "some-other-tag" }))
1304
+ expect(ExceptionHandling).to receive(:log_info).with(/Unable to execute honeybadger_auto_tags callback. boom/)
1305
+ ExceptionHandling.log_error(exception, nil, honeybadger_tags: ["some-other-tag"])
1306
+ end
1307
+ end
1248
1308
  end
1249
1309
 
1250
1310
  context "ExceptionHandling < 3.0 " do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exception_handling
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.15.0
4
+ version: 2.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-07 00:00:00.000000000 Z
11
+ date: 2023-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
@@ -211,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
211
  - !ruby/object:Gem::Version
212
212
  version: '0'
213
213
  requirements: []
214
- rubygems_version: 3.4.7
214
+ rubygems_version: 3.1.6
215
215
  signing_key:
216
216
  specification_version: 4
217
217
  summary: Invoca's exception handling logger/emailer layer, based on exception_notifier.