exception_handling 2.4.4 → 2.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de262141b33b7c4cb5e68018569d0465144097e36d0b85c268646cb0bfb5eb3f
4
- data.tar.gz: cdbd41bfd1df237f6d6c3c1788ac52a0ed75314c5fbf63b3cb549edc21aeb3ed
3
+ metadata.gz: 5720f1d81733d8912d7777a97e57f29c412b05fd938ebe073c91973d1b948685
4
+ data.tar.gz: b7f587666d212e629be8603cbb711c76ade2917d1a03c91e541f87b7c3eb09c6
5
5
  SHA512:
6
- metadata.gz: a64db1560f94c6c62ced1d7b5afadd1ece6618ee62e41db250b2384e8193b29ec35e39b9389edb2a1e130b2aebf77b4e7851b8173a705b8a7b620284f62e1b9e
7
- data.tar.gz: c2efcf1378cf70651ccd1e2e4f3f0f85ff4fe49714f7547d3b4517a0afb1c657f7a8def9dd4339aa7bd510fc714d53b27cc7120fe109fa12eea2c8bbfe98de6e
6
+ metadata.gz: c7138e98374c2f2609500fdd2c11c7bee9211d6f6d548e5c1afe3191318e5966c48ff8fd6e6af2230f5c3ceb6ca44ece1535a85009881e9bd748adcf7d8438e9
7
+ data.tar.gz: 6f6cdf2a385a190f1439488c3ac0e3dbaa4c5726a6dfdb4c8bb647b7e86c4dd06bb8d2740cc6e1ee54dfebd77a65b204884fd0bd76346367d201eb624f036757
@@ -4,6 +4,20 @@ 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.6.0] - Unreleased
8
+ ### Changed
9
+ - Calling `log_warning` will now log with Severity::WARNING rather than FATAL.
10
+ - Reordered the logging to put the exception class next to the message.
11
+
12
+ ## [2.5.0] - 2020-08-19
13
+ ### Added
14
+ - The `**log_context` passed to `log_error`/`log_warning`/`log_info` is now
15
+ passed into `Honeybadger.notify()`, in `context: { log_context: ... }`.
16
+
17
+ ### Fixed
18
+ - Silenced test warning noise by no longer running ruby -w.
19
+ - Renamed a constant to ALLOWLIST.
20
+
7
21
  ## [2.4.4] - 2020-08-10
8
22
  ### Fixed
9
23
  - `ExceptionHandling.logger = nil` no longer displays an "implicit extend" deprecation warning.
@@ -28,7 +42,9 @@ Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0
28
42
  ### Changed
29
43
  - No longer depends on hobo_support. Uses invoca-utils 0.3 instead.
30
44
 
31
- [2.4.3]: https://github.com/Invoca/exception_handling/compare/v2.4.3...v2.4.4
45
+ [2.6.0]: https://github.com/Invoca/exception_handling/compare/v2.5.0...v2.6.0
46
+ [2.5.0]: https://github.com/Invoca/exception_handling/compare/v2.4.4...v2.5.0
47
+ [2.4.4]: https://github.com/Invoca/exception_handling/compare/v2.4.3...v2.4.4
32
48
  [2.4.3]: https://github.com/Invoca/exception_handling/compare/v2.4.2...v2.4.3
33
49
  [2.4.2]: https://github.com/Invoca/exception_handling/compare/v2.4.1...v2.4.2
34
50
  [2.4.1]: https://github.com/Invoca/exception_handling/compare/v2.4.0...v2.4.1
@@ -8,7 +8,7 @@ GIT
8
8
  PATH
9
9
  remote: .
10
10
  specs:
11
- exception_handling (2.4.4)
11
+ exception_handling (2.6.0)
12
12
  actionmailer (>= 4.2, < 7.0)
13
13
  actionpack (>= 4.2, < 7.0)
14
14
  activesupport (>= 4.2, < 7.0)
@@ -55,7 +55,7 @@ GEM
55
55
  builder (3.2.3)
56
56
  coderay (1.1.2)
57
57
  concurrent-ruby (1.1.5)
58
- contextual_logger (0.8.0)
58
+ contextual_logger (0.9.1)
59
59
  activesupport
60
60
  json
61
61
  crass (1.0.6)
@@ -68,7 +68,7 @@ GEM
68
68
  invoca-utils (0.4.1)
69
69
  jaro_winkler (1.5.3)
70
70
  json (2.3.1)
71
- loofah (2.6.0)
71
+ loofah (2.7.0)
72
72
  crass (~> 1.0.2)
73
73
  nokogiri (>= 1.5.9)
74
74
  mail (2.7.1)
data/Rakefile CHANGED
@@ -4,6 +4,8 @@
4
4
  require "bundler/gem_tasks"
5
5
  require 'rake/testtask'
6
6
 
7
+ require_relative 'test/rake_test_warning_false'
8
+
7
9
  task default: :test
8
10
 
9
11
  Rake::TestTask.new do |t|
@@ -193,7 +193,9 @@ module ExceptionHandling # never included
193
193
  def log_error(exception_or_string, exception_context = '', controller = nil, treat_like_warning: false, **log_context, &data_callback)
194
194
  ex = make_exception(exception_or_string)
195
195
  timestamp = set_log_error_timestamp
196
- exception_info = ExceptionInfo.new(ex, exception_context, timestamp, controller || current_controller, data_callback)
196
+ exception_info = ExceptionInfo.new(ex, exception_context, timestamp,
197
+ controller: controller || current_controller, data_callback: data_callback,
198
+ log_context: log_context)
197
199
 
198
200
  if stub_handler
199
201
  stub_handler.handle_stub_log_error(exception_info.data)
@@ -220,7 +222,13 @@ module ExceptionHandling # never included
220
222
  #
221
223
  def write_exception_to_log(ex, exception_context, timestamp, log_context = {})
222
224
  ActiveSupport::Deprecation.silence do
223
- ExceptionHandling.logger.fatal("\nExceptionHandlingError (Error:#{timestamp}) #{ex.class} #{exception_context} (#{encode_utf8(ex.message.to_s)}):\n " + clean_backtrace(ex).join("\n ") + "\n\n", log_context)
225
+ log_message = "#{exception_context}\n#{ex.class}: (#{encode_utf8(ex.message.to_s)}):\n " + clean_backtrace(ex).join("\n ") + "\n\n"
226
+
227
+ if ex.is_a?(Warning)
228
+ ExceptionHandling.logger.warn("\nExceptionHandlingWarning (Warning:#{timestamp}) #{log_message}", log_context)
229
+ else
230
+ ExceptionHandling.logger.fatal("\nExceptionHandlingError (Error:#{timestamp}) #{log_message}", log_context)
231
+ end
224
232
  end
225
233
  end
226
234
 
@@ -3,7 +3,7 @@
3
3
  module ExceptionHandling
4
4
  class ExceptionInfo
5
5
 
6
- ENVIRONMENT_WHITELIST = [
6
+ ENVIRONMENT_ALLOWLIST = [
7
7
  /^HTTP_/,
8
8
  /^QUERY_/,
9
9
  /^REQUEST_/,
@@ -46,16 +46,20 @@ module ExceptionHandling
46
46
  EOS
47
47
 
48
48
  SECTIONS = [:request, :session, :environment, :backtrace, :event_response].freeze
49
- HONEYBADGER_CONTEXT_SECTIONS = [:timestamp, :error_class, :exception_context, :server, :scm_revision, :notes, :user_details, :request, :session, :environment, :backtrace, :event_response].freeze
49
+ HONEYBADGER_CONTEXT_SECTIONS = [:timestamp, :error_class, :exception_context, :server, :scm_revision, :notes,
50
+ :user_details, :request, :session, :environment, :backtrace, :event_response, :log_context].freeze
50
51
 
51
52
  attr_reader :exception, :controller, :exception_context, :timestamp
52
53
 
53
- def initialize(exception, exception_context, timestamp, controller = nil, data_callback = nil)
54
+ def initialize(exception, exception_context, timestamp, controller: nil, data_callback: nil, log_context: nil)
54
55
  @exception = exception
55
56
  @exception_context = exception_context
56
57
  @timestamp = timestamp
57
58
  @controller = controller || controller_from_context(exception_context)
58
59
  @data_callback = data_callback
60
+ @merged_log_context = if log_context # merge into the surrounding context just like ContextualLogger does when logging
61
+ ExceptionHandling.logger.current_context_for_thread.deep_merge(log_context)
62
+ end
59
63
  end
60
64
 
61
65
  def data
@@ -176,7 +180,7 @@ module ExceptionHandling
176
180
 
177
181
  def clean_environment(env)
178
182
  Hash[ env.map do |k, v|
179
- [k, v] if !"#{k}: #{v}".in?(ENVIRONMENT_OMIT) && ENVIRONMENT_WHITELIST.any? { |regex| k =~ regex }
183
+ [k, v] if !"#{k}: #{v}".in?(ENVIRONMENT_OMIT) && ENVIRONMENT_ALLOWLIST.any? { |regex| k =~ regex }
180
184
  end.compact ]
181
185
  end
182
186
 
@@ -267,6 +271,7 @@ module ExceptionHandling
267
271
  data = enhanced_data.dup
268
272
  data[:server] = ExceptionHandling.server_name
269
273
  data[:exception_context] = deep_clean_hash(@exception_context) if @exception_context.present?
274
+ data[:log_context] = @merged_log_context
270
275
  unstringify_sections(data)
271
276
  context_data = HONEYBADGER_CONTEXT_SECTIONS.reduce({}) do |context, section|
272
277
  if data[section].present?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExceptionHandling
4
- VERSION = '2.4.4'
4
+ VERSION = '2.6.0'
5
5
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Rake 11+ has a misfeature where @warning = true by default
4
+ # See https://github.com/ruby/rake/pull/97/files
5
+ # This causes all tests to be run with `ruby -w`, causing a huge number of warnings
6
+ # from gems we don't control and overwhelming our test output.
7
+ # This patch reverts that.
8
+
9
+ _ = Rake::TestTask
10
+
11
+ class Rake::TestTask
12
+ module SetWarningFalseMixin
13
+ def initialize(*args)
14
+ super
15
+ self.warning = false
16
+ end
17
+ end
18
+
19
+ prepend SetWarningFalseMixin
20
+ end
@@ -33,16 +33,20 @@ class LoggerStub
33
33
  clear
34
34
  end
35
35
 
36
+ def debug(message, log_context = {})
37
+ logged << { message: message, context: log_context, severity: 'DEBUG' }
38
+ end
39
+
36
40
  def info(message, log_context = {})
37
- logged << { message: message, context: log_context }
41
+ logged << { message: message, context: log_context, severity: 'INFO' }
38
42
  end
39
43
 
40
44
  def warn(message, log_context = {})
41
- logged << { message: message, context: log_context }
45
+ logged << { message: message, context: log_context, severity: 'WARN' }
42
46
  end
43
47
 
44
48
  def fatal(message, log_context = {})
45
- logged << { message: message, context: log_context }
49
+ logged << { message: message, context: log_context, severity: 'FATAL' }
46
50
  end
47
51
 
48
52
  def clear
@@ -29,7 +29,7 @@ module ExceptionHandling
29
29
  exception_context = {
30
30
  "action_controller.instance" => Object.new
31
31
  }
32
- exception_info = ExceptionInfo.new(@exception, exception_context, @timestamp, @controller)
32
+ exception_info = ExceptionInfo.new(@exception, exception_context, @timestamp, controller: @controller)
33
33
  assert_equal @controller, exception_info.controller
34
34
  assert_not_equal exception_context["action_controller.instance"], exception_info.controller
35
35
  end
@@ -107,7 +107,7 @@ module ExceptionHandling
107
107
  request_uri = "host/path"
108
108
  controller = create_dummy_controller(env, parameters, session, request_uri)
109
109
  data_callback = ->(data) { data[:custom_section] = "value" }
110
- exception_info = ExceptionInfo.new(@exception, "custom context data", @timestamp, controller, data_callback)
110
+ exception_info = ExceptionInfo.new(@exception, "custom context data", @timestamp, controller: controller, data_callback: data_callback)
111
111
 
112
112
  dont_allow(exception_info).extract_and_merge_controller_data
113
113
  dont_allow(exception_info).customize_from_data_callback
@@ -177,7 +177,7 @@ module ExceptionHandling
177
177
  end
178
178
 
179
179
  should "include controller data when available" do
180
- exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, @controller)
180
+ exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: @controller)
181
181
  expected_data = {
182
182
  "error_class" => "StandardError",
183
183
  "error_string" => "StandardError: something went wrong",
@@ -220,7 +220,7 @@ module ExceptionHandling
220
220
  end
221
221
 
222
222
  should "add to_s attribute to specific sections that have their content in hash format" do
223
- exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, @controller)
223
+ exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: @controller)
224
224
  expected_data = {
225
225
  "error_class" => "StandardError",
226
226
  "error_string" => "StandardError: something went wrong",
@@ -251,7 +251,7 @@ module ExceptionHandling
251
251
  should "filter out sensitive parameters like passwords" do
252
252
  @controller.request.parameters[:password] = "super_secret"
253
253
  @controller.request.parameters[:user] = { "password" => "also super secret", "password_confirmation" => "also super secret" }
254
- exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, @controller)
254
+ exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: @controller)
255
255
  expected_params = {
256
256
  "password" => "[FILTERED]",
257
257
  "advertiser_id" => 435, "controller" => "dummy",
@@ -265,7 +265,7 @@ module ExceptionHandling
265
265
  end
266
266
 
267
267
  should "include the changes from the custom data callback" do
268
- exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, nil, @data_callback)
268
+ exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: nil, data_callback: @data_callback)
269
269
  expected_data = {
270
270
  "error_class" => "StandardError",
271
271
  "error_string" => "StandardError: something went wrong",
@@ -331,7 +331,7 @@ module ExceptionHandling
331
331
  request_uri = "host/path"
332
332
  controller = create_dummy_controller(env, parameters, session, request_uri)
333
333
  exception = StandardError.new("Request to click domain rejected")
334
- exception_info = ExceptionInfo.new(exception, {}, Time.now, controller)
334
+ exception_info = ExceptionInfo.new(exception, nil, Time.now, controller: controller)
335
335
  assert_equal true, exception_info.enhanced_data[:request].is_a?(Hash)
336
336
  description = exception_info.exception_description
337
337
  assert_not_nil description
@@ -340,11 +340,11 @@ module ExceptionHandling
340
340
 
341
341
  should "return same description object for related errors (avoid reloading exception catalog from disk)" do
342
342
  exception = StandardError.new("No route matches")
343
- exception_info = ExceptionInfo.new(exception, {}, Time.now)
343
+ exception_info = ExceptionInfo.new(exception, nil, Time.now)
344
344
  description = exception_info.exception_description
345
345
 
346
346
  repeat_ex = StandardError.new("No route matches 2")
347
- repeat_ex_info = ExceptionInfo.new(repeat_ex, {}, Time.now)
347
+ repeat_ex_info = ExceptionInfo.new(repeat_ex, nil, Time.now)
348
348
  assert_equal description.object_id, repeat_ex_info.exception_description.object_id
349
349
  end
350
350
  end
@@ -368,7 +368,7 @@ module ExceptionHandling
368
368
  session = { username: 'smith' }
369
369
  request_uri = "host/path"
370
370
  controller = create_dummy_controller(env, parameters, session, request_uri)
371
- exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller)
371
+ exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: controller)
372
372
 
373
373
  assert_equal 'some_controller', exception_info.controller_name
374
374
  end
@@ -384,7 +384,7 @@ module ExceptionHandling
384
384
  should "be enabled when Honeybadger is defined and exception is not in the filter list" do
385
385
  stub(ExceptionHandling).honeybadger_defined? { true }
386
386
  exception = StandardError.new("something went wrong")
387
- exception_info = ExceptionInfo.new(exception, {}, Time.now)
387
+ exception_info = ExceptionInfo.new(exception, nil, Time.now)
388
388
  assert_nil exception_info.exception_description
389
389
  assert_equal true, exception_info.send_to_honeybadger?
390
390
  end
@@ -392,7 +392,7 @@ module ExceptionHandling
392
392
  should "be enabled when Honeybadger is defined and exception is on the filter list with the flag turned on" do
393
393
  stub(ExceptionHandling).honeybadger_defined? { true }
394
394
  exception = StandardError.new("No route matches")
395
- exception_info = ExceptionInfo.new(exception, {}, Time.now)
395
+ exception_info = ExceptionInfo.new(exception, nil, Time.now)
396
396
  assert_not_nil exception_info.exception_description
397
397
  assert_equal true, exception_info.exception_description.send_to_honeybadger
398
398
  assert_equal true, exception_info.send_to_honeybadger?
@@ -401,7 +401,7 @@ module ExceptionHandling
401
401
  should "be disabled when Honeybadger is defined and exception is on the filter list with the flag turned off" do
402
402
  stub(ExceptionHandling).honeybadger_defined? { true }
403
403
  exception = StandardError.new("No route matches")
404
- exception_info = ExceptionInfo.new(exception, {}, Time.now)
404
+ exception_info = ExceptionInfo.new(exception, nil, Time.now)
405
405
  assert_not_nil exception_info.exception_description
406
406
  stub(exception_info.exception_description).send_to_honeybadger { false }
407
407
  assert_equal false, exception_info.send_to_honeybadger?
@@ -410,7 +410,7 @@ module ExceptionHandling
410
410
  should "be disabled when Honeybadger is not defined" do
411
411
  stub(ExceptionHandling).honeybadger_defined? { false }
412
412
  exception = StandardError.new("something went wrong")
413
- exception_info = ExceptionInfo.new(exception, {}, Time.now)
413
+ exception_info = ExceptionInfo.new(exception, nil, Time.now)
414
414
  assert_nil exception_info.exception_description
415
415
  assert_equal false, exception_info.send_to_honeybadger?
416
416
  end
@@ -438,7 +438,7 @@ module ExceptionHandling
438
438
  data[:other_section] = "This should not be included in the response"
439
439
  end
440
440
  timestamp = Time.now
441
- exception_info = ExceptionInfo.new(exception, exception_context, timestamp, controller, data_callback)
441
+ exception_info = ExceptionInfo.new(exception, exception_context, timestamp, controller: controller, data_callback: data_callback)
442
442
 
443
443
  expected_data = {
444
444
  timestamp: timestamp,
@@ -95,7 +95,7 @@ module ExceptionHandling
95
95
  assert_equal "#<ExceptionHandling::HoneybadgerCallbacksTest::TestRaiseOnInspectWithId @id=123 [error 'RuntimeError: some error' while calling #inspect]>", result
96
96
  end
97
97
 
98
- should "handle exceptions for objects responding to to_pik" do
98
+ should "handle exceptions for objects responding to to_pk" do
99
99
  result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, TestRaiseOnInspectWithToPk.new, ['password'])
100
100
  assert_equal "#<ExceptionHandling::HoneybadgerCallbacksTest::TestRaiseOnInspectWithToPk @pk=SomeRecord-123 [error 'RuntimeError: some error' while calling #inspect]>", result
101
101
  end
@@ -149,6 +149,11 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
149
149
  assert_not_empty logged_excluding_reload_filter.last[:context]
150
150
  assert_equal logged_excluding_reload_filter.last[:context], service_name: 'exception_handling'
151
151
  end
152
+
153
+ should "log with Severity::FATAL" do
154
+ ExceptionHandling.log_error('This is a Warning', service_name: 'exception_handling')
155
+ assert_equal logged_excluding_reload_filter.last[:severity], 'FATAL'
156
+ end
152
157
  end
153
158
 
154
159
  context "#log_warning" do
@@ -165,24 +170,53 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
165
170
  assert_not_empty logged_excluding_reload_filter.last[:context]
166
171
  assert_equal logged_excluding_reload_filter.last[:context], service_name: 'exception_handling'
167
172
  end
173
+
174
+ should "log with Severity::WARN" do
175
+ ExceptionHandling.log_warning('This is a Warning', service_name: 'exception_handling')
176
+ assert_equal logged_excluding_reload_filter.last[:severity], 'WARN'
177
+ end
168
178
  end
169
179
 
170
180
  context "#log_info" do
171
181
  should "take in additional key word args as logging context and pass them to the logger" do
172
- ExceptionHandling.log_warning('This is an Info', service_name: 'exception_handling')
182
+ ExceptionHandling.log_info('This is an Info', service_name: 'exception_handling')
173
183
  assert_match(/This is an Info/, logged_excluding_reload_filter.last[:message])
174
184
  assert_not_empty logged_excluding_reload_filter.last[:context]
175
185
  assert_equal logged_excluding_reload_filter.last[:context], service_name: 'exception_handling'
176
186
  end
187
+
188
+ should "log with Severity::INFO" do
189
+ ExceptionHandling.log_info('This is a Warning', service_name: 'exception_handling')
190
+ assert_equal logged_excluding_reload_filter.last[:severity], 'INFO'
191
+ end
177
192
  end
178
193
 
179
194
  context "#log_debug" do
180
195
  should "take in additional key word args as logging context and pass them to the logger" do
181
- ExceptionHandling.log_warning('This is a Debug', service_name: 'exception_handling')
196
+ ExceptionHandling.log_debug('This is a Debug', service_name: 'exception_handling')
182
197
  assert_match(/This is a Debug/, logged_excluding_reload_filter.last[:message])
183
198
  assert_not_empty logged_excluding_reload_filter.last[:context]
184
199
  assert_equal logged_excluding_reload_filter.last[:context], service_name: 'exception_handling'
185
200
  end
201
+
202
+ should "log with Severity::DEBUG" do
203
+ ExceptionHandling.log_debug('This is a Warning', service_name: 'exception_handling')
204
+ assert_equal logged_excluding_reload_filter.last[:severity], 'DEBUG'
205
+ end
206
+ end
207
+
208
+ context "#write_exception_to_log" do
209
+ should "log warnings with Severity::WARN" do
210
+ warning = ExceptionHandling::Warning.new('This is a Warning')
211
+ ExceptionHandling.write_exception_to_log(warning, '', Time.now.to_i, service_name: 'exception_handling')
212
+ assert_equal logged_excluding_reload_filter.last[:severity], 'WARN'
213
+ end
214
+
215
+ should "log everything else with Severity::FATAL" do
216
+ error = RuntimeError.new('This is a runtime error')
217
+ ExceptionHandling.write_exception_to_log(error, '', Time.now.to_i, service_name: 'exception_handling')
218
+ assert_equal logged_excluding_reload_filter.last[:severity], 'FATAL'
219
+ end
186
220
  end
187
221
 
188
222
  context "configuration with custom_data_hook or post_log_error_hook" do
@@ -339,7 +373,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
339
373
 
340
374
  if ActionView::VERSION::MAJOR >= 5
341
375
  should "log an exception with call stack if an ActionView template exception is raised." do
342
- mock(ExceptionHandling.logger).fatal(/\(Error:\d+\) ActionView::Template::Error \(blah\):\n /, anything)
376
+ mock(ExceptionHandling.logger).fatal(/\(Error:\d+\) \nActionView::Template::Error: \(blah\):\n /, anything)
343
377
  ExceptionHandling.ensure_safe do
344
378
  begin
345
379
  # Rails 5 made the switch from ActionView::TemplateError taking in the original exception
@@ -352,7 +386,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
352
386
  end
353
387
  else
354
388
  should "log an exception with call stack if an ActionView template exception is raised." do
355
- mock(ExceptionHandling.logger).fatal(/\(Error:\d+\) ActionView::Template::Error \(blah\):\n /, anything)
389
+ mock(ExceptionHandling.logger).fatal(/\(Error:\d+\) \nActionView::Template::Error: \(blah\):\n /, anything)
356
390
  ExceptionHandling.ensure_safe { raise ActionView::TemplateError.new({}, ArgumentError.new("blah")) }
357
391
  end
358
392
  end
@@ -375,7 +409,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
375
409
  end
376
410
 
377
411
  should "allow a message to be appended to the error when logged." do
378
- mock(ExceptionHandling.logger).fatal(/mooo \(blah\):\n.*exception_handling_test\.rb/, anything)
412
+ mock(ExceptionHandling.logger).fatal(/mooo\nArgumentError: \(blah\):\n.*exception_handling_test\.rb/, anything)
379
413
  b = ExceptionHandling.ensure_safe("mooo") { raise ArgumentError, "blah" }
380
414
  assert_nil b
381
415
  end
@@ -383,7 +417,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
383
417
  should "only rescue StandardError and descendents" do
384
418
  assert_raise(Exception) { ExceptionHandling.ensure_safe("mooo") { raise Exception } }
385
419
 
386
- mock(ExceptionHandling.logger).fatal(/mooo \(blah\):\n.*exception_handling_test\.rb/, anything)
420
+ mock(ExceptionHandling.logger).fatal(/mooo\nStandardError: \(blah\):\n.*exception_handling_test\.rb/, anything)
387
421
 
388
422
  b = ExceptionHandling.ensure_safe("mooo") { raise StandardError, "blah" }
389
423
  assert_nil b
@@ -414,7 +448,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
414
448
  end
415
449
 
416
450
  should "allow a message to be appended to the error when logged." do
417
- mock(ExceptionHandling.logger).fatal(/mooo \(blah\):\n.*exception_handling_test\.rb/, anything)
451
+ mock(ExceptionHandling.logger).fatal(/mooo\nArgumentError: \(blah\):\n.*exception_handling_test\.rb/, anything)
418
452
  b = ExceptionHandling.ensure_completely_safe("mooo") { raise ArgumentError, "blah" }
419
453
  assert_nil b
420
454
  end
@@ -471,7 +505,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
471
505
  ExceptionHandling.ensure_escalation("ensure context") { raise ArgumentError, "first_test_exception" }
472
506
 
473
507
  assert_match(/ArgumentError.*first_test_exception/, log_fatals[0].first)
474
- assert_match(/safe_email_deliver.*Delivery Error/, log_fatals[1].first)
508
+ assert_match(/safe_email_deliver.*Delivery Error/m, log_fatals[1].first)
475
509
 
476
510
  assert_equal 2, log_fatals.size, log_fatals.inspect
477
511
 
@@ -541,7 +575,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
541
575
  should "include the timestamp when the exception is logged" do
542
576
  capture_notifications
543
577
 
544
- mock(ExceptionHandling.logger).fatal(/\(Error:517033020\) ArgumentError context \(blah\):\n.*exception_handling_test\.rb/, anything)
578
+ mock(ExceptionHandling.logger).fatal(/\(Error:517033020\) context\nArgumentError: \(blah\):\n.*exception_handling_test\.rb/, anything)
545
579
  b = ExceptionHandling.ensure_safe("context") { raise ArgumentError, "blah" }
546
580
  assert_nil b
547
581
 
@@ -621,66 +655,122 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
621
655
  ExceptionHandling.log_error(exception_with_nil_message)
622
656
  end
623
657
 
624
- should "send error details and relevant context data to Honeybadger" do
625
- Time.now_override = Time.now
626
- env = { server: "fe98" }
627
- parameters = { advertiser_id: 435, controller: "some_controller" }
628
- session = { username: "jsmith" }
629
- request_uri = "host/path"
630
- controller = create_dummy_controller(env, parameters, session, request_uri)
631
- stub(ExceptionHandling).server_name { "invoca_fe98" }
632
-
633
- exception = StandardError.new("Some Exception")
634
- exception.set_backtrace([
635
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
636
- "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
637
- ])
638
- exception_context = { "SERVER_NAME" => "exceptional.com" }
639
-
640
- honeybadger_data = nil
641
- mock(Honeybadger).notify.with_any_args do |data|
642
- honeybadger_data = data
658
+ context "with stubbed values" do
659
+ setup do
660
+ Time.now_override = Time.now
661
+ @env = { server: "fe98" }
662
+ @parameters = { advertiser_id: 435, controller: "some_controller" }
663
+ @session = { username: "jsmith" }
664
+ @request_uri = "host/path"
665
+ @controller = create_dummy_controller(@env, @parameters, @session, @request_uri)
666
+ stub(ExceptionHandling).server_name { "invoca_fe98" }
667
+
668
+ @exception = StandardError.new("Some Exception")
669
+ @exception.set_backtrace([
670
+ "test/unit/exception_handling_test.rb:847:in `exception_1'",
671
+ "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
672
+ ])
673
+ @exception_context = { "SERVER_NAME" => "exceptional.com" }
643
674
  end
644
- ExceptionHandling.log_error(exception, exception_context, controller) do |data|
645
- data[:scm_revision] = "5b24eac37aaa91f5784901e9aabcead36fd9df82"
646
- data[:user_details] = { username: "jsmith" }
647
- data[:event_response] = "Event successfully received"
648
- data[:other_section] = "This should not be included in the response"
675
+
676
+ should "send error details and relevant context data to Honeybadger with log_context" do
677
+ honeybadger_data = nil
678
+ mock(Honeybadger).notify.with_any_args do |data|
679
+ honeybadger_data = data
680
+ end
681
+ ExceptionHandling.logger.global_context = { service_name: "rails", region: "AWS-us-east-1" }
682
+ log_context = { log_source: "gem/listen", service_name: "bin/console" }
683
+ ExceptionHandling.log_error(@exception, @exception_context, @controller, **log_context) do |data|
684
+ data[:scm_revision] = "5b24eac37aaa91f5784901e9aabcead36fd9df82"
685
+ data[:user_details] = { username: "jsmith" }
686
+ data[:event_response] = "Event successfully received"
687
+ data[:other_section] = "This should not be included in the response"
688
+ end
689
+
690
+ expected_data = {
691
+ error_class: :"Test Exception",
692
+ error_message: "Some Exception",
693
+ controller: "some_controller",
694
+ exception: @exception,
695
+ context: {
696
+ timestamp: Time.now.to_i,
697
+ error_class: "StandardError",
698
+ server: "invoca_fe98",
699
+ exception_context: { "SERVER_NAME" => "exceptional.com" },
700
+ scm_revision: "5b24eac37aaa91f5784901e9aabcead36fd9df82",
701
+ notes: "this is used by a test",
702
+ user_details: { "username" => "jsmith" },
703
+ request: {
704
+ "params" => { "advertiser_id" => 435, "controller" => "some_controller" },
705
+ "rails_root" => "Rails.root not defined. Is this a test environment?",
706
+ "url" => "host/path"
707
+ },
708
+ session: {
709
+ "key" => nil,
710
+ "data" => { "username" => "jsmith" }
711
+ },
712
+ environment: {
713
+ "SERVER_NAME" => "exceptional.com"
714
+ },
715
+ backtrace: [
716
+ "test/unit/exception_handling_test.rb:847:in `exception_1'",
717
+ "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
718
+ ],
719
+ event_response: "Event successfully received",
720
+ log_context: { "service_name" => "bin/console", "region" => "AWS-us-east-1", "log_source" => "gem/listen" }
721
+ }
722
+ }
723
+ assert_equal_with_diff expected_data, honeybadger_data
649
724
  end
650
725
 
651
- expected_data = {
652
- error_class: :"Test Exception",
653
- error_message: "Some Exception",
654
- controller: "some_controller",
655
- exception: exception,
656
- context: {
657
- timestamp: Time.now.to_i,
658
- error_class: "StandardError",
659
- server: "invoca_fe98",
660
- exception_context: { "SERVER_NAME" => "exceptional.com" },
661
- scm_revision: "5b24eac37aaa91f5784901e9aabcead36fd9df82",
662
- notes: "this is used by a test",
663
- user_details: { "username" => "jsmith" },
664
- request: {
665
- "params" => { "advertiser_id" => 435, "controller" => "some_controller" },
666
- "rails_root" => "Rails.root not defined. Is this a test environment?",
667
- "url" => "host/path"
668
- },
669
- session: {
670
- "key" => nil,
671
- "data" => { "username" => "jsmith" }
672
- },
673
- environment: {
674
- "SERVER_NAME" => "exceptional.com"
675
- },
676
- backtrace: [
677
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
678
- "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
679
- ],
680
- event_response: "Event successfully received"
726
+ should "send error details and relevant context data to Honeybadger with empty log_context" do
727
+ honeybadger_data = nil
728
+ mock(Honeybadger).notify.with_any_args do |data|
729
+ honeybadger_data = data
730
+ end
731
+ ExceptionHandling.logger.global_context = {}
732
+ log_context = {}
733
+ ExceptionHandling.log_error(@exception, @exception_context, @controller, **log_context) do |data|
734
+ data[:scm_revision] = "5b24eac37aaa91f5784901e9aabcead36fd9df82"
735
+ data[:user_details] = { username: "jsmith" }
736
+ data[:event_response] = "Event successfully received"
737
+ data[:other_section] = "This should not be included in the response"
738
+ end
739
+
740
+ expected_data = {
741
+ error_class: :"Test Exception",
742
+ error_message: "Some Exception",
743
+ controller: "some_controller",
744
+ exception: @exception,
745
+ context: {
746
+ timestamp: Time.now.to_i,
747
+ error_class: "StandardError",
748
+ server: "invoca_fe98",
749
+ exception_context: { "SERVER_NAME" => "exceptional.com" },
750
+ scm_revision: "5b24eac37aaa91f5784901e9aabcead36fd9df82",
751
+ notes: "this is used by a test",
752
+ user_details: { "username" => "jsmith" },
753
+ request: {
754
+ "params" => { "advertiser_id" => 435, "controller" => "some_controller" },
755
+ "rails_root" => "Rails.root not defined. Is this a test environment?",
756
+ "url" => "host/path"
757
+ },
758
+ session: {
759
+ "key" => nil,
760
+ "data" => { "username" => "jsmith" }
761
+ },
762
+ environment: {
763
+ "SERVER_NAME" => "exceptional.com"
764
+ },
765
+ backtrace: [
766
+ "test/unit/exception_handling_test.rb:847:in `exception_1'",
767
+ "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
768
+ ],
769
+ event_response: "Event successfully received"
770
+ }
681
771
  }
682
- }
683
- assert_equal_with_diff expected_data, honeybadger_data
772
+ assert_equal_with_diff expected_data, honeybadger_data
773
+ end
684
774
  end
685
775
 
686
776
  context "with post_log_error_hook set" 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.4.4
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-11 00:00:00.000000000 Z
11
+ date: 2020-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
@@ -150,6 +150,7 @@ files:
150
150
  - lib/exception_handling/version.rb
151
151
  - test/helpers/controller_helpers.rb
152
152
  - test/helpers/exception_helpers.rb
153
+ - test/rake_test_warning_false.rb
153
154
  - test/test_helper.rb
154
155
  - test/unit/exception_handling/exception_catalog_test.rb
155
156
  - test/unit/exception_handling/exception_description_test.rb
@@ -168,7 +169,7 @@ licenses: []
168
169
  metadata:
169
170
  source_code_uri: https://github.com/Invoca/exception_handling
170
171
  allowed_push_host: https://rubygems.org
171
- post_install_message:
172
+ post_install_message:
172
173
  rdoc_options: []
173
174
  require_paths:
174
175
  - lib
@@ -184,13 +185,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
185
  version: '0'
185
186
  requirements: []
186
187
  rubygems_version: 3.0.3
187
- signing_key:
188
+ signing_key:
188
189
  specification_version: 4
189
190
  summary: Invoca's exception handling logger/emailer layer, based on exception_notifier.
190
191
  Works with Rails or EventMachine or EventMachine+Synchrony.
191
192
  test_files:
192
193
  - test/helpers/controller_helpers.rb
193
194
  - test/helpers/exception_helpers.rb
195
+ - test/rake_test_warning_false.rb
194
196
  - test/test_helper.rb
195
197
  - test/unit/exception_handling/exception_catalog_test.rb
196
198
  - test/unit/exception_handling/exception_description_test.rb