exception_handling 2.17.0.pre.tstarck.1 → 3.0.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 +5 -5
- data/.gitignore +0 -3
- data/.ruby-version +1 -1
- data/Gemfile +16 -12
- data/Gemfile.lock +138 -153
- data/README.md +21 -90
- data/Rakefile +11 -8
- data/exception_handling.gemspec +10 -14
- data/lib/exception_handling/exception_info.rb +11 -15
- data/lib/exception_handling/honeybadger_callbacks.rb +59 -0
- data/lib/exception_handling/log_stub_error.rb +1 -2
- data/lib/exception_handling/methods.rb +53 -6
- data/lib/exception_handling/testing.rb +10 -20
- data/lib/exception_handling/version.rb +1 -1
- data/lib/exception_handling.rb +34 -135
- data/semaphore_ci/setup.sh +3 -0
- data/{spec → test}/helpers/exception_helpers.rb +2 -2
- data/{spec/spec_helper.rb → test/test_helper.rb} +45 -75
- data/test/unit/exception_handling/exception_catalog_test.rb +85 -0
- data/test/unit/exception_handling/exception_description_test.rb +82 -0
- data/{spec/unit/exception_handling/exception_info_spec.rb → test/unit/exception_handling/exception_info_test.rb} +114 -170
- data/test/unit/exception_handling/honeybadger_callbacks_test.rb +122 -0
- data/{spec/unit/exception_handling/log_error_stub_spec.rb → test/unit/exception_handling/log_error_stub_test.rb} +22 -38
- data/{spec/unit/exception_handling/mailer_spec.rb → test/unit/exception_handling/mailer_test.rb} +18 -17
- data/test/unit/exception_handling/methods_test.rb +84 -0
- data/test/unit/exception_handling/sensu_test.rb +52 -0
- data/test/unit/exception_handling_test.rb +1109 -0
- metadata +59 -99
- data/.github/CODEOWNERS +0 -1
- data/.github/workflows/pipeline.yml +0 -36
- data/.rspec +0 -3
- data/.tool-versions +0 -1
- data/Appraisals +0 -19
- data/CHANGELOG.md +0 -149
- data/gemfiles/rails_5.gemfile +0 -18
- data/gemfiles/rails_6.gemfile +0 -18
- data/gemfiles/rails_7.gemfile +0 -18
- data/lib/exception_handling/escalate_callback.rb +0 -19
- data/lib/exception_handling/logging_methods.rb +0 -27
- data/spec/rake_test_warning_false.rb +0 -20
- data/spec/unit/exception_handling/escalate_callback_spec.rb +0 -81
- data/spec/unit/exception_handling/exception_catalog_spec.rb +0 -85
- data/spec/unit/exception_handling/exception_description_spec.rb +0 -82
- data/spec/unit/exception_handling/logging_methods_spec.rb +0 -38
- data/spec/unit/exception_handling/methods_spec.rb +0 -105
- data/spec/unit/exception_handling/sensu_spec.rb +0 -51
- data/spec/unit/exception_handling_spec.rb +0 -1465
- /data/{spec → test}/helpers/controller_helpers.rb +0 -0
@@ -1,50 +1,42 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/time'
|
5
|
+
require 'active_support/test_case'
|
6
|
+
require 'active_model'
|
7
|
+
require 'action_mailer'
|
8
|
+
require 'action_dispatch'
|
9
|
+
require 'hobo_support'
|
10
|
+
require 'shoulda'
|
11
|
+
require 'rr'
|
12
|
+
require 'minitest/autorun'
|
7
13
|
require 'pry'
|
8
|
-
require 'pry-byebug'
|
9
14
|
require 'honeybadger'
|
10
15
|
require 'contextual_logger'
|
11
16
|
|
12
17
|
require 'exception_handling'
|
13
18
|
require 'exception_handling/testing'
|
14
19
|
|
20
|
+
ActiveSupport::TestCase.test_order = :sorted
|
21
|
+
|
15
22
|
class LoggerStub
|
16
|
-
include ContextualLogger
|
17
|
-
attr_accessor :logged
|
23
|
+
include ContextualLogger
|
24
|
+
attr_accessor :logged
|
18
25
|
|
19
26
|
def initialize
|
20
|
-
@level = Logger::Severity::DEBUG
|
21
|
-
@progname = nil
|
22
|
-
@logdev = nil
|
23
27
|
clear
|
24
28
|
end
|
25
29
|
|
26
|
-
def
|
27
|
-
|
28
|
-
logged << { message: message, context: log_context, severity: 'DEBUG' }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def info(message, **log_context)
|
33
|
-
super.tap do
|
34
|
-
logged << { message: message, context: log_context, severity: 'INFO' }
|
35
|
-
end
|
30
|
+
def info(message, log_context = {})
|
31
|
+
logged << { message: message, context: log_context }
|
36
32
|
end
|
37
33
|
|
38
|
-
def warn(message,
|
39
|
-
|
40
|
-
logged << { message: message, context: log_context, severity: 'WARN' }
|
41
|
-
end
|
34
|
+
def warn(message, log_context = {})
|
35
|
+
logged << { message: message, context: log_context }
|
42
36
|
end
|
43
37
|
|
44
|
-
def fatal(message,
|
45
|
-
|
46
|
-
logged << { message: message, context: log_context, severity: 'FATAL' }
|
47
|
-
end
|
38
|
+
def fatal(message, log_context = {})
|
39
|
+
logged << { message: message, context: log_context }
|
48
40
|
end
|
49
41
|
|
50
42
|
def clear
|
@@ -85,17 +77,27 @@ end
|
|
85
77
|
|
86
78
|
ActionMailer::Base.delivery_method = :test
|
87
79
|
|
80
|
+
_ = ActiveSupport
|
81
|
+
_ = ActiveSupport::TestCase
|
88
82
|
|
89
|
-
|
90
|
-
|
91
|
-
class << self
|
92
|
-
attr_accessor :constant_overrides
|
93
|
-
end
|
83
|
+
class ActiveSupport::TestCase
|
84
|
+
@@constant_overrides = []
|
94
85
|
|
86
|
+
setup do
|
87
|
+
unless @@constant_overrides.nil? || @@constant_overrides.empty?
|
88
|
+
raise "Uh-oh! constant_overrides left over: #{@@constant_overrides.inspect}"
|
89
|
+
end
|
90
|
+
|
91
|
+
unless defined?(Rails) && defined?(Rails.env)
|
92
|
+
module ::Rails
|
93
|
+
class << self
|
94
|
+
attr_writer :env
|
95
95
|
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
def env
|
97
|
+
@env ||= 'test'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
99
101
|
end
|
100
102
|
|
101
103
|
Time.now_override = nil
|
@@ -115,8 +117,8 @@ module TestHelper
|
|
115
117
|
ExceptionHandling.sensu_prefix = ""
|
116
118
|
end
|
117
119
|
|
118
|
-
|
119
|
-
|
120
|
+
teardown do
|
121
|
+
@@constant_overrides&.reverse&.each do |parent_module, k, v|
|
120
122
|
ExceptionHandling.ensure_safe "constant cleanup #{k.inspect}, #{parent_module}(#{parent_module.class})::#{v.inspect}(#{v.class})" do
|
121
123
|
silence_warnings do
|
122
124
|
if v == :never_defined
|
@@ -127,7 +129,7 @@ module TestHelper
|
|
127
129
|
end
|
128
130
|
end
|
129
131
|
end
|
130
|
-
|
132
|
+
@@constant_overrides = []
|
131
133
|
end
|
132
134
|
|
133
135
|
def set_test_const(const_name, value)
|
@@ -147,7 +149,7 @@ module TestHelper
|
|
147
149
|
end
|
148
150
|
end
|
149
151
|
|
150
|
-
|
152
|
+
@@constant_overrides << [final_parent_module, final_const_name, original_value]
|
151
153
|
|
152
154
|
silence_warnings { final_parent_module.const_set(final_const_name, value) }
|
153
155
|
end
|
@@ -159,15 +161,15 @@ module TestHelper
|
|
159
161
|
else
|
160
162
|
original_count = 0
|
161
163
|
end
|
162
|
-
|
164
|
+
assert_equal expected, ActionMailer::Base.deliveries.size - original_count, "wrong number of emails#{': ' + message.to_s if message}"
|
163
165
|
end
|
164
166
|
end
|
165
167
|
|
166
168
|
def assert_equal_with_diff(arg1, arg2, msg = '')
|
167
169
|
if arg1 == arg2
|
168
|
-
|
170
|
+
assert true # To keep the assertion count accurate
|
169
171
|
else
|
170
|
-
|
172
|
+
assert_equal arg1, arg2, "#{msg}\n#{Diff.compare(arg1, arg2)}"
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
@@ -198,35 +200,3 @@ class Time
|
|
198
200
|
end
|
199
201
|
end
|
200
202
|
end
|
201
|
-
|
202
|
-
RSpec.configure do |config|
|
203
|
-
config.add_formatter(RspecJunitFormatter, 'spec/reports/rspec.xml')
|
204
|
-
config.include TestHelper
|
205
|
-
|
206
|
-
config.before(:each) do
|
207
|
-
setup_constant_overrides
|
208
|
-
unless defined?(Rails) && defined?(Rails.env)
|
209
|
-
module Rails
|
210
|
-
class << self
|
211
|
-
attr_writer :env
|
212
|
-
|
213
|
-
def env
|
214
|
-
@env ||= 'test'
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
config.after(:each) do
|
222
|
-
teardown_constant_overrides
|
223
|
-
end
|
224
|
-
|
225
|
-
config.mock_with :rspec do |mocks|
|
226
|
-
mocks.verify_partial_doubles = true
|
227
|
-
end
|
228
|
-
|
229
|
-
config.expect_with(:rspec, :test_unit)
|
230
|
-
|
231
|
-
RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 2_000
|
232
|
-
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('../../test_helper', __dir__)
|
4
|
+
|
5
|
+
module ExceptionHandling
|
6
|
+
class ExceptionCatalogTest < ActiveSupport::TestCase
|
7
|
+
|
8
|
+
context "With stubbed yaml content" do
|
9
|
+
setup do
|
10
|
+
filter_list = { exception1: { error: "my error message" },
|
11
|
+
exception2: { error: "some other message", session: "misc data" } }
|
12
|
+
stub(YAML).load_file { filter_list }
|
13
|
+
|
14
|
+
# bump modified time up to get the above filter loaded
|
15
|
+
stub(File).mtime { incrementing_mtime }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "with loaded data" do
|
19
|
+
setup do
|
20
|
+
stub(File).mtime { incrementing_mtime }
|
21
|
+
@exception_catalog = ExceptionCatalog.new(ExceptionHandling.filter_list_filename)
|
22
|
+
@exception_catalog.send :load_file
|
23
|
+
end
|
24
|
+
|
25
|
+
should "have loaded filters" do
|
26
|
+
assert_equal 2, @exception_catalog.instance_eval("@filters").size
|
27
|
+
end
|
28
|
+
|
29
|
+
should "find messages in the catalog" do
|
30
|
+
assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
|
31
|
+
end
|
32
|
+
|
33
|
+
should "find matching data" do
|
34
|
+
exception_description = @exception_catalog.find(error: "this is my error message, which should match something")
|
35
|
+
assert exception_description
|
36
|
+
assert_equal :exception1, exception_description.filter_name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
should "write errors loading the yaml file directly to the log file" do
|
41
|
+
@exception_catalog = ExceptionCatalog.new(ExceptionHandling.filter_list_filename)
|
42
|
+
|
43
|
+
mock(ExceptionHandling).log_error.never
|
44
|
+
mock(ExceptionHandling).write_exception_to_log(anything, "ExceptionCatalog#refresh_filters: ./config/exception_filters.yml", anything)
|
45
|
+
mock(@exception_catalog).load_file { raise "noooooo" }
|
46
|
+
|
47
|
+
@exception_catalog.find({})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "with live yaml content" do
|
52
|
+
setup do
|
53
|
+
@filename = File.expand_path('../../../config/exception_filters.yml', __dir__)
|
54
|
+
@exception_catalog = ExceptionCatalog.new(@filename)
|
55
|
+
assert_nothing_raised "Loading the exception filter should not raise" do
|
56
|
+
@exception_catalog.send :load_file
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
should "load the filter data" do
|
61
|
+
assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
|
62
|
+
assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with no yaml content" do
|
67
|
+
setup do
|
68
|
+
@exception_catalog = ExceptionCatalog.new(nil)
|
69
|
+
end
|
70
|
+
|
71
|
+
should "not load filter data" do
|
72
|
+
mock(ExceptionHandling).write_exception_to_log.with_any_args.never
|
73
|
+
@exception_catalog.find(error: "Scott says unlikely to ever match")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def incrementing_mtime
|
80
|
+
@mtime ||= Time.now
|
81
|
+
@mtime += 1.day
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('../../test_helper', __dir__)
|
4
|
+
|
5
|
+
module ExceptionHandling
|
6
|
+
class ExceptionDescriptionTest < ActiveSupport::TestCase
|
7
|
+
|
8
|
+
context "Filter" do
|
9
|
+
should "allow direct matching of strings" do
|
10
|
+
@f = ExceptionDescription.new(:filter1, error: "my error message")
|
11
|
+
assert @f.match?('error' => "my error message")
|
12
|
+
end
|
13
|
+
|
14
|
+
should "allow direct matching of strings on with symbol keys" do
|
15
|
+
@f = ExceptionDescription.new(:filter1, error: "my error message")
|
16
|
+
assert @f.match?(error: "my error message")
|
17
|
+
end
|
18
|
+
|
19
|
+
should "allow wildcards to cross line boundries" do
|
20
|
+
@f = ExceptionDescription.new(:filter1, error: "my error message.*with multiple lines")
|
21
|
+
assert @f.match?(error: "my error message\nwith more than one, with multiple lines")
|
22
|
+
end
|
23
|
+
|
24
|
+
should "complain when no regexps have a value" do
|
25
|
+
assert_raise(ArgumentError, "has all blank regexe") { ExceptionDescription.new(:filter1, error: nil) }
|
26
|
+
end
|
27
|
+
|
28
|
+
should "report when an invalid key is passed" do
|
29
|
+
assert_raise(ArgumentError, "Unknown section: not_a_parameter") { ExceptionDescription.new(:filter1, error: "my error message", not_a_parameter: false) }
|
30
|
+
end
|
31
|
+
|
32
|
+
should "allow send_to_honeybadger to be specified and have it disabled by default" do
|
33
|
+
assert !ExceptionDescription.new(:filter1, error: "my error message", send_to_honeybadger: false).send_to_honeybadger
|
34
|
+
assert ExceptionDescription.new(:filter1, error: "my error message", send_to_honeybadger: true).send_to_honeybadger
|
35
|
+
assert !ExceptionDescription.new(:filter1, error: "my error message").send_to_honeybadger
|
36
|
+
end
|
37
|
+
|
38
|
+
should "allow send_metric to be configured" do
|
39
|
+
assert !ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).send_metric
|
40
|
+
assert ExceptionDescription.new(:filter1, error: "my error message").send_metric
|
41
|
+
end
|
42
|
+
|
43
|
+
should "provide metric name" do
|
44
|
+
assert_equal "filter1", ExceptionDescription.new(:filter1, error: "my error message").metric_name
|
45
|
+
assert_equal "some_other_metric_name", ExceptionDescription.new(:filter1, error: "my error message", metric_name: :some_other_metric_name).metric_name
|
46
|
+
end
|
47
|
+
|
48
|
+
should "replace spaces in metric name" do
|
49
|
+
@f = ExceptionDescription.new(:"filter has spaces", error: "my error message")
|
50
|
+
assert_equal "filter_has_spaces", @f.metric_name
|
51
|
+
end
|
52
|
+
|
53
|
+
should "allow notes to be recorded" do
|
54
|
+
assert_nil ExceptionDescription.new(:filter1, error: "my error message").notes
|
55
|
+
assert_equal "a long string", ExceptionDescription.new(:filter1, error: "my error message", notes: "a long string").notes
|
56
|
+
end
|
57
|
+
|
58
|
+
should "not consider config options in the filter set" do
|
59
|
+
assert ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).match?(error: "my error message")
|
60
|
+
assert ExceptionDescription.new(:filter1, error: "my error message", metric_name: "false").match?(error: "my error message")
|
61
|
+
assert ExceptionDescription.new(:filter1, error: "my error message", notes: "hey").match?(error: "my error message")
|
62
|
+
end
|
63
|
+
|
64
|
+
should "provide exception details" do
|
65
|
+
exception_description = ExceptionDescription.new(:filter1, error: "my error message", notes: "hey")
|
66
|
+
|
67
|
+
expected = { "send_metric" => true, "metric_name" => "filter1", "notes" => "hey" }
|
68
|
+
|
69
|
+
assert_equal expected, exception_description.exception_data
|
70
|
+
end
|
71
|
+
|
72
|
+
should "match multiple email addresses" do
|
73
|
+
mobi = "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for 'mcc@mobistreak.com'"
|
74
|
+
credit = "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for 'damon@thecreditpros.com'"
|
75
|
+
|
76
|
+
exception_description = ExceptionDescription.new(:filter1, error: "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for '(mcc\@mobistreak|damon\@thecreditpros).com'")
|
77
|
+
assert exception_description.match?(error: mobi), "does not match mobi"
|
78
|
+
assert exception_description.match?(error: credit), "does not match credit"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|