exception_handling 2.4.4.pre.1 → 2.5.1.pre.1

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: 5e18b802032b87ce35aee9ab2a3eebd4177686e5ff9bca74ed0f32e5c266e517
4
- data.tar.gz: 12a870a3f4ed762298cd13a045edba06b470c9aea9d29324b0642163779610d0
3
+ metadata.gz: 5c3561b45435bb79e5ee48f090362ea006a0d522ab5b61809af57a56951d5aff
4
+ data.tar.gz: b711a085d3a0049dd5dfbf6e454cb4e948f5f20b2a5d561d6b05a40f0d5c33d8
5
5
  SHA512:
6
- metadata.gz: 121a94c85c7dad8f56003674dcee796e1dd80e7e96c31012e0343614ca6375f192734c4c0b2e4fd8025f4f66d8cc306ed157a28a8bf213b5ec94af6c5a7dc65d
7
- data.tar.gz: 20d94f407272de21c341362a18be4500a984aa6f2fad05d9706ee1ed6943d2537f281aff315c48e028095dcdfbe491bb0ef3cc32c35eff6473ab176259ab30ab
6
+ metadata.gz: a98fa1af28748a12facbe69b35d56641204db4f43d700970115a476b6689f591e9cc9cd5301a6d8709751f386642f51dd07657efb27f85de1e6ad61173a0e08d
7
+ data.tar.gz: 143f2f54b21e73299b2486ddff7532e4142fa01e5e92544f1cf4c07d8fd2f5d6de53cacace2089816ae81ccad850e820569e8a60efebb3196e7524e3dd8f26bd
@@ -4,10 +4,23 @@ 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.4.4] - Unreleased
7
+ ## [2.5.1] - Unreleased
8
8
  ### Changed
9
9
  - Calling `log_warning` will now log with Severity::WARNING rather than FATAL.
10
10
 
11
+ ## [2.5.0] - 2020-08-19
12
+ ### Added
13
+ - The `**log_context` passed to `log_error`/`log_warning`/`log_info` is now
14
+ passed into `Honeybadger.notify()`, in `context: { log_context: ... }`.
15
+
16
+ ### Fixed
17
+ - Silenced test warning noise by no longer running ruby -w.
18
+ - Renamed a constant to ALLOWLIST.
19
+
20
+ ## [2.4.4] - 2020-08-10
21
+ ### Fixed
22
+ - `ExceptionHandling.logger = nil` no longer displays an "implicit extend" deprecation warning.
23
+
11
24
  ## [2.4.3] - 2020-05-14
12
25
  ### Deprecated
13
26
  - In `ExceptionHandling.logger=`, implicit `logger.extend ContextualLogger::LoggerMixin` is now deprecated.
@@ -28,6 +41,8 @@ Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0
28
41
  ### Changed
29
42
  - No longer depends on hobo_support. Uses invoca-utils 0.3 instead.
30
43
 
44
+ [2.5.1]: https://github.com/Invoca/exception_handling/compare/v2.5.0...v2.5.1
45
+ [2.5.0]: https://github.com/Invoca/exception_handling/compare/v2.4.4...v2.5.0
31
46
  [2.4.4]: https://github.com/Invoca/exception_handling/compare/v2.4.3...v2.4.4
32
47
  [2.4.3]: https://github.com/Invoca/exception_handling/compare/v2.4.2...v2.4.3
33
48
  [2.4.2]: https://github.com/Invoca/exception_handling/compare/v2.4.1...v2.4.2
@@ -8,7 +8,7 @@ GIT
8
8
  PATH
9
9
  remote: .
10
10
  specs:
11
- exception_handling (2.4.4.pre.1)
11
+ exception_handling (2.5.1.pre.1)
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.9.0)
58
+ contextual_logger (0.9.1)
59
59
  activesupport
60
60
  json
61
61
  crass (1.0.6)
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|
@@ -57,7 +57,7 @@ module ExceptionHandling # never included
57
57
  Deprecation3_0 = ActiveSupport::Deprecation.new('3.0', 'exception_handling')
58
58
 
59
59
  def logger=(logger)
60
- @logger = if logger.is_a?(ContextualLogger::LoggerMixin)
60
+ @logger = if logger.nil? || logger.is_a?(ContextualLogger::LoggerMixin)
61
61
  logger
62
62
  else
63
63
  Deprecation3_0.deprecation_warning('implicit extend with ContextualLogger::LoggerMixin', 'extend your logger instance or include into your logger class first')
@@ -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,12 +222,12 @@ 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
- log_message = "\nExceptionHandlingError (Error:#{timestamp}) #{ex.class} #{exception_context} (#{encode_utf8(ex.message.to_s)}):\n " + clean_backtrace(ex).join("\n ") + "\n\n"
225
+ log_message = "#{exception_context}\n#{ex.class}: (#{encode_utf8(ex.message.to_s)}):\n " + clean_backtrace(ex).join("\n ") + "\n\n"
224
226
 
225
227
  if ex.is_a?(Warning)
226
- ExceptionHandling.logger.warn(log_message, log_context)
228
+ ExceptionHandling.logger.warn("\nExceptionHandlingWarning (Warning:#{timestamp}) #{log_message}", log_context)
227
229
  else
228
- ExceptionHandling.logger.fatal(log_message, log_context)
230
+ ExceptionHandling.logger.fatal("\nExceptionHandlingError (Error:#{timestamp}) #{log_message}", log_context)
229
231
  end
230
232
  end
231
233
  end
@@ -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.pre.1'
4
+ VERSION = '2.5.1.pre.1'
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
@@ -126,6 +126,11 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
126
126
  assert_equal ancestors, ExceptionHandling.logger.singleton_class.ancestors.*.name
127
127
  end
128
128
 
129
+ should "allow logger = nil (no deprecation warning)" do
130
+ mock(STDERR).puts(/DEPRECATION WARNING/).never
131
+ ExceptionHandling.logger = nil
132
+ end
133
+
129
134
  should "[deprecated] mix in ContextualLogger::Mixin if not there" do
130
135
  mock(STDERR).puts(/DEPRECATION WARNING: implicit extend with ContextualLogger::LoggerMixin is deprecated and will be removed from exception_handling 3\.0/)
131
136
  logger = Logger.new('/dev/null')
@@ -144,6 +149,11 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
144
149
  assert_not_empty logged_excluding_reload_filter.last[:context]
145
150
  assert_equal logged_excluding_reload_filter.last[:context], service_name: 'exception_handling'
146
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
147
157
  end
148
158
 
149
159
  context "#log_warning" do
@@ -160,24 +170,53 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
160
170
  assert_not_empty logged_excluding_reload_filter.last[:context]
161
171
  assert_equal logged_excluding_reload_filter.last[:context], service_name: 'exception_handling'
162
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
163
178
  end
164
179
 
165
180
  context "#log_info" do
166
181
  should "take in additional key word args as logging context and pass them to the logger" do
167
- ExceptionHandling.log_warning('This is an Info', service_name: 'exception_handling')
182
+ ExceptionHandling.log_info('This is an Info', service_name: 'exception_handling')
168
183
  assert_match(/This is an Info/, logged_excluding_reload_filter.last[:message])
169
184
  assert_not_empty logged_excluding_reload_filter.last[:context]
170
185
  assert_equal logged_excluding_reload_filter.last[:context], service_name: 'exception_handling'
171
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
172
192
  end
173
193
 
174
194
  context "#log_debug" do
175
195
  should "take in additional key word args as logging context and pass them to the logger" do
176
- ExceptionHandling.log_warning('This is a Debug', service_name: 'exception_handling')
196
+ ExceptionHandling.log_debug('This is a Debug', service_name: 'exception_handling')
177
197
  assert_match(/This is a Debug/, logged_excluding_reload_filter.last[:message])
178
198
  assert_not_empty logged_excluding_reload_filter.last[:context]
179
199
  assert_equal logged_excluding_reload_filter.last[:context], service_name: 'exception_handling'
180
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
181
220
  end
182
221
 
183
222
  context "configuration with custom_data_hook or post_log_error_hook" do
@@ -334,7 +373,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
334
373
 
335
374
  if ActionView::VERSION::MAJOR >= 5
336
375
  should "log an exception with call stack if an ActionView template exception is raised." do
337
- 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)
338
377
  ExceptionHandling.ensure_safe do
339
378
  begin
340
379
  # Rails 5 made the switch from ActionView::TemplateError taking in the original exception
@@ -347,7 +386,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
347
386
  end
348
387
  else
349
388
  should "log an exception with call stack if an ActionView template exception is raised." do
350
- 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)
351
390
  ExceptionHandling.ensure_safe { raise ActionView::TemplateError.new({}, ArgumentError.new("blah")) }
352
391
  end
353
392
  end
@@ -370,7 +409,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
370
409
  end
371
410
 
372
411
  should "allow a message to be appended to the error when logged." do
373
- 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)
374
413
  b = ExceptionHandling.ensure_safe("mooo") { raise ArgumentError, "blah" }
375
414
  assert_nil b
376
415
  end
@@ -378,7 +417,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
378
417
  should "only rescue StandardError and descendents" do
379
418
  assert_raise(Exception) { ExceptionHandling.ensure_safe("mooo") { raise Exception } }
380
419
 
381
- 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)
382
421
 
383
422
  b = ExceptionHandling.ensure_safe("mooo") { raise StandardError, "blah" }
384
423
  assert_nil b
@@ -409,7 +448,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
409
448
  end
410
449
 
411
450
  should "allow a message to be appended to the error when logged." do
412
- 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)
413
452
  b = ExceptionHandling.ensure_completely_safe("mooo") { raise ArgumentError, "blah" }
414
453
  assert_nil b
415
454
  end
@@ -466,7 +505,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
466
505
  ExceptionHandling.ensure_escalation("ensure context") { raise ArgumentError, "first_test_exception" }
467
506
 
468
507
  assert_match(/ArgumentError.*first_test_exception/, log_fatals[0].first)
469
- assert_match(/safe_email_deliver.*Delivery Error/, log_fatals[1].first)
508
+ assert_match(/safe_email_deliver.*Delivery Error/m, log_fatals[1].first)
470
509
 
471
510
  assert_equal 2, log_fatals.size, log_fatals.inspect
472
511
 
@@ -536,7 +575,7 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
536
575
  should "include the timestamp when the exception is logged" do
537
576
  capture_notifications
538
577
 
539
- 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)
540
579
  b = ExceptionHandling.ensure_safe("context") { raise ArgumentError, "blah" }
541
580
  assert_nil b
542
581
 
@@ -616,66 +655,122 @@ class ExceptionHandlingTest < ActiveSupport::TestCase
616
655
  ExceptionHandling.log_error(exception_with_nil_message)
617
656
  end
618
657
 
619
- should "send error details and relevant context data to Honeybadger" do
620
- Time.now_override = Time.now
621
- env = { server: "fe98" }
622
- parameters = { advertiser_id: 435, controller: "some_controller" }
623
- session = { username: "jsmith" }
624
- request_uri = "host/path"
625
- controller = create_dummy_controller(env, parameters, session, request_uri)
626
- stub(ExceptionHandling).server_name { "invoca_fe98" }
627
-
628
- exception = StandardError.new("Some Exception")
629
- exception.set_backtrace([
630
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
631
- "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
632
- ])
633
- exception_context = { "SERVER_NAME" => "exceptional.com" }
634
-
635
- honeybadger_data = nil
636
- mock(Honeybadger).notify.with_any_args do |data|
637
- 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" }
638
674
  end
639
- ExceptionHandling.log_error(exception, exception_context, controller) do |data|
640
- data[:scm_revision] = "5b24eac37aaa91f5784901e9aabcead36fd9df82"
641
- data[:user_details] = { username: "jsmith" }
642
- data[:event_response] = "Event successfully received"
643
- 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
644
724
  end
645
725
 
646
- expected_data = {
647
- error_class: :"Test Exception",
648
- error_message: "Some Exception",
649
- controller: "some_controller",
650
- exception: exception,
651
- context: {
652
- timestamp: Time.now.to_i,
653
- error_class: "StandardError",
654
- server: "invoca_fe98",
655
- exception_context: { "SERVER_NAME" => "exceptional.com" },
656
- scm_revision: "5b24eac37aaa91f5784901e9aabcead36fd9df82",
657
- notes: "this is used by a test",
658
- user_details: { "username" => "jsmith" },
659
- request: {
660
- "params" => { "advertiser_id" => 435, "controller" => "some_controller" },
661
- "rails_root" => "Rails.root not defined. Is this a test environment?",
662
- "url" => "host/path"
663
- },
664
- session: {
665
- "key" => nil,
666
- "data" => { "username" => "jsmith" }
667
- },
668
- environment: {
669
- "SERVER_NAME" => "exceptional.com"
670
- },
671
- backtrace: [
672
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
673
- "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
674
- ],
675
- 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
+ }
676
771
  }
677
- }
678
- assert_equal_with_diff expected_data, honeybadger_data
772
+ assert_equal_with_diff expected_data, honeybadger_data
773
+ end
679
774
  end
680
775
 
681
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.pre.1
4
+ version: 2.5.1.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-18 00:00:00.000000000 Z
11
+ date: 2020-08-25 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
@@ -191,6 +192,7 @@ summary: Invoca's exception handling logger/emailer layer, based on exception_no
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