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 +4 -4
- data/CHANGELOG.md +17 -1
- data/Gemfile.lock +3 -3
- data/Rakefile +2 -0
- data/lib/exception_handling.rb +10 -2
- data/lib/exception_handling/exception_info.rb +9 -4
- data/lib/exception_handling/version.rb +1 -1
- data/test/rake_test_warning_false.rb +20 -0
- data/test/test_helper.rb +7 -3
- data/test/unit/exception_handling/exception_info_test.rb +15 -15
- data/test/unit/exception_handling/honeybadger_callbacks_test.rb +1 -1
- data/test/unit/exception_handling_test.rb +155 -65
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5720f1d81733d8912d7777a97e57f29c412b05fd938ebe073c91973d1b948685
|
4
|
+
data.tar.gz: b7f587666d212e629be8603cbb711c76ade2917d1a03c91e541f87b7c3eb09c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7138e98374c2f2609500fdd2c11c7bee9211d6f6d548e5c1afe3191318e5966c48ff8fd6e6af2230f5c3ceb6ca44ece1535a85009881e9bd748adcf7d8438e9
|
7
|
+
data.tar.gz: 6f6cdf2a385a190f1439488c3ac0e3dbaa4c5726a6dfdb4c8bb647b7e86c4dd06bb8d2740cc6e1ee54dfebd77a65b204884fd0bd76346367d201eb624f036757
|
data/CHANGELOG.md
CHANGED
@@ -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.
|
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
|
data/Gemfile.lock
CHANGED
@@ -8,7 +8,7 @@ GIT
|
|
8
8
|
PATH
|
9
9
|
remote: .
|
10
10
|
specs:
|
11
|
-
exception_handling (2.
|
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.
|
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.
|
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
data/lib/exception_handling.rb
CHANGED
@@ -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,
|
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
|
-
|
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
|
-
|
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,
|
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
|
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) &&
|
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?
|
@@ -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
|
data/test/test_helper.rb
CHANGED
@@ -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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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
|
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.
|
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.
|
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+\)
|
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+\)
|
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
|
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\)
|
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
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
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
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
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
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
"SERVER_NAME" => "exceptional.com"
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
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
|
-
|
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
|
+
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
|
+
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
|