airbrake-ruby 4.13.3-java → 5.0.0.rc.1-java
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/lib/airbrake-ruby.rb +23 -32
- data/lib/airbrake-ruby/async_sender.rb +1 -1
- data/lib/airbrake-ruby/config.rb +65 -13
- data/lib/airbrake-ruby/config/processor.rb +80 -0
- data/lib/airbrake-ruby/config/validator.rb +4 -0
- data/lib/airbrake-ruby/filter_chain.rb +15 -1
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +2 -1
- data/lib/airbrake-ruby/filters/{keys_whitelist.rb → keys_allowlist.rb} +3 -3
- data/lib/airbrake-ruby/filters/{keys_blacklist.rb → keys_blocklist.rb} +3 -3
- data/lib/airbrake-ruby/filters/keys_filter.rb +5 -5
- data/lib/airbrake-ruby/notice_notifier.rb +6 -0
- data/lib/airbrake-ruby/performance_notifier.rb +1 -1
- data/lib/airbrake-ruby/remote_settings.rb +128 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
- data/lib/airbrake-ruby/sync_sender.rb +1 -1
- data/lib/airbrake-ruby/thread_pool.rb +1 -0
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/airbrake_spec.rb +71 -36
- data/spec/config/processor_spec.rb +223 -0
- data/spec/config/validator_spec.rb +18 -1
- data/spec/config_spec.rb +38 -6
- data/spec/filter_chain_spec.rb +27 -0
- data/spec/filters/git_last_checkout_filter_spec.rb +20 -3
- data/spec/filters/{keys_whitelist_spec.rb → keys_allowlist_spec.rb} +10 -10
- data/spec/filters/{keys_blacklist_spec.rb → keys_blocklist_spec.rb} +10 -10
- data/spec/filters/sql_filter_spec.rb +3 -3
- data/spec/notice_notifier/options_spec.rb +4 -4
- data/spec/performance_notifier_spec.rb +2 -2
- data/spec/remote_settings/settings_data_spec.rb +327 -0
- data/spec/remote_settings_spec.rb +212 -0
- data/spec/sync_sender_spec.rb +3 -1
- data/spec/thread_pool_spec.rb +25 -5
- metadata +20 -12
@@ -0,0 +1,223 @@
|
|
1
|
+
RSpec.describe Airbrake::Config::Processor do
|
2
|
+
let(:notifier) { Airbrake::NoticeNotifier.new }
|
3
|
+
|
4
|
+
describe "#process_blocklist" do
|
5
|
+
let(:config) { Airbrake::Config.new(blocklist_keys: %w[a b c]) }
|
6
|
+
|
7
|
+
context "when there ARE blocklist keys" do
|
8
|
+
it "adds the blocklist filter" do
|
9
|
+
described_class.new(config).process_blocklist(notifier)
|
10
|
+
expect(notifier.has_filter?(Airbrake::Filters::KeysBlocklist)).to eq(true)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when there are NO blocklist keys" do
|
15
|
+
let(:config) { Airbrake::Config.new(blocklist_keys: %w[]) }
|
16
|
+
|
17
|
+
it "doesn't add the blocklist filter" do
|
18
|
+
described_class.new(config).process_blocklist(notifier)
|
19
|
+
expect(notifier.has_filter?(Airbrake::Filters::KeysBlocklist))
|
20
|
+
.to eq(false)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#process_allowlist" do
|
26
|
+
let(:config) { Airbrake::Config.new(allowlist_keys: %w[a b c]) }
|
27
|
+
|
28
|
+
context "when there ARE allowlist keys" do
|
29
|
+
it "adds the allowlist filter" do
|
30
|
+
described_class.new(config).process_allowlist(notifier)
|
31
|
+
expect(notifier.has_filter?(Airbrake::Filters::KeysAllowlist)).to eq(true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when there are NO allowlist keys" do
|
36
|
+
let(:config) { Airbrake::Config.new(allowlist_keys: %w[]) }
|
37
|
+
|
38
|
+
it "doesn't add the allowlist filter" do
|
39
|
+
described_class.new(config).process_allowlist(notifier)
|
40
|
+
expect(notifier.has_filter?(Airbrake::Filters::KeysAllowlist))
|
41
|
+
.to eq(false)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#process_remote_configuration" do
|
47
|
+
context "when the config doesn't define a project_id" do
|
48
|
+
let(:config) { Airbrake::Config.new(project_id: nil) }
|
49
|
+
|
50
|
+
it "doesn't set remote settings" do
|
51
|
+
expect(Airbrake::RemoteSettings).not_to receive(:poll)
|
52
|
+
described_class.new(config).process_remote_configuration
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when the config defines a project_id" do
|
57
|
+
context "and when remote configuration is false" do
|
58
|
+
let(:config) do
|
59
|
+
Airbrake::Config.new(project_id: 123, __remote_configuration: false)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "doesn't set remote settings" do
|
63
|
+
expect(Airbrake::RemoteSettings).not_to receive(:poll)
|
64
|
+
described_class.new(config).process_remote_configuration
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "and when remote configuration is true" do
|
69
|
+
let(:config) do
|
70
|
+
Airbrake::Config.new(project_id: 123, __remote_configuration: true)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "sets remote settings" do
|
74
|
+
expect(Airbrake::RemoteSettings).to receive(:poll)
|
75
|
+
described_class.new(config).process_remote_configuration
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#add_filters" do
|
82
|
+
context "when there's a root directory" do
|
83
|
+
let(:config) { Airbrake::Config.new(root_directory: '/abc') }
|
84
|
+
|
85
|
+
it "adds RootDirectoryFilter" do
|
86
|
+
described_class.new(config).add_filters(notifier)
|
87
|
+
expect(notifier.has_filter?(Airbrake::Filters::RootDirectoryFilter))
|
88
|
+
.to eq(true)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "adds GitRevisionFilter" do
|
92
|
+
described_class.new(config).add_filters(notifier)
|
93
|
+
expect(notifier.has_filter?(Airbrake::Filters::GitRevisionFilter))
|
94
|
+
.to eq(true)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "adds GitRepositoryFilter" do
|
98
|
+
described_class.new(config).add_filters(notifier)
|
99
|
+
expect(notifier.has_filter?(Airbrake::Filters::GitRepositoryFilter))
|
100
|
+
.to eq(true)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "adds GitLastCheckoutFilter" do
|
104
|
+
described_class.new(config).add_filters(notifier)
|
105
|
+
expect(notifier.has_filter?(Airbrake::Filters::GitLastCheckoutFilter))
|
106
|
+
.to eq(true)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when there's NO root directory" do
|
111
|
+
let(:config) { Airbrake::Config.new(root_directory: nil) }
|
112
|
+
|
113
|
+
it "doesn't add RootDirectoryFilter" do
|
114
|
+
described_class.new(config).add_filters(notifier)
|
115
|
+
expect(notifier.has_filter?(Airbrake::Filters::RootDirectoryFilter))
|
116
|
+
.to eq(false)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "doesn't add GitRevisionFilter" do
|
120
|
+
described_class.new(config).add_filters(notifier)
|
121
|
+
expect(notifier.has_filter?(Airbrake::Filters::GitRevisionFilter))
|
122
|
+
.to eq(false)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "doesn't add GitRepositoryFilter" do
|
126
|
+
described_class.new(config).add_filters(notifier)
|
127
|
+
expect(notifier.has_filter?(Airbrake::Filters::GitRepositoryFilter))
|
128
|
+
.to eq(false)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "doesn't add GitLastCheckoutFilter" do
|
132
|
+
described_class.new(config).add_filters(notifier)
|
133
|
+
expect(notifier.has_filter?(Airbrake::Filters::GitLastCheckoutFilter))
|
134
|
+
.to eq(false)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#poll_callback" do
|
140
|
+
let(:logger) { Logger.new(File::NULL) }
|
141
|
+
|
142
|
+
let(:config) do
|
143
|
+
Airbrake::Config.new(
|
144
|
+
project_id: 123,
|
145
|
+
__remote_configuration: true,
|
146
|
+
logger: logger,
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
let(:data) do
|
151
|
+
instance_double(Airbrake::RemoteSettings::SettingsData)
|
152
|
+
end
|
153
|
+
|
154
|
+
before do
|
155
|
+
allow(data).to receive(:to_h)
|
156
|
+
allow(data).to receive(:error_host)
|
157
|
+
allow(data).to receive(:apm_host)
|
158
|
+
allow(data).to receive(:error_notifications?)
|
159
|
+
allow(data).to receive(:performance_stats?)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "logs given data" do
|
163
|
+
expect(logger).to receive(:debug).with(/applying remote settings/)
|
164
|
+
described_class.new(config).poll_callback(data)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "sets the error_notifications option" do
|
168
|
+
config.error_notifications = false
|
169
|
+
expect(data).to receive(:error_notifications?).and_return(true)
|
170
|
+
|
171
|
+
described_class.new(config).poll_callback(data)
|
172
|
+
expect(config.error_notifications).to eq(true)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "sets the performance_stats option" do
|
176
|
+
config.performance_stats = false
|
177
|
+
expect(data).to receive(:performance_stats?).and_return(true)
|
178
|
+
|
179
|
+
described_class.new(config).poll_callback(data)
|
180
|
+
expect(config.performance_stats).to eq(true)
|
181
|
+
end
|
182
|
+
|
183
|
+
context "when error_host returns a value" do
|
184
|
+
it "sets the error_host option" do
|
185
|
+
config.error_host = 'http://api.airbrake.io'
|
186
|
+
allow(data).to receive(:error_host).and_return('https://api.example.com')
|
187
|
+
|
188
|
+
described_class.new(config).poll_callback(data)
|
189
|
+
expect(config.error_host).to eq('https://api.example.com')
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context "when error_host returns nil" do
|
194
|
+
it "doesn't modify the error_host option" do
|
195
|
+
config.error_host = 'http://api.airbrake.io'
|
196
|
+
allow(data).to receive(:error_host).and_return(nil)
|
197
|
+
|
198
|
+
described_class.new(config).poll_callback(data)
|
199
|
+
expect(config.error_host).to eq('http://api.airbrake.io')
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context "when apm_host returns a value" do
|
204
|
+
it "sets the apm_host option" do
|
205
|
+
config.apm_host = 'http://api.airbrake.io'
|
206
|
+
allow(data).to receive(:apm_host).and_return('https://api.example.com')
|
207
|
+
|
208
|
+
described_class.new(config).poll_callback(data)
|
209
|
+
expect(config.apm_host).to eq('https://api.example.com')
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context "when apm_host returns nil" do
|
214
|
+
it "doesn't modify the apm_host option" do
|
215
|
+
config.apm_host = 'http://api.airbrake.io'
|
216
|
+
allow(data).to receive(:apm_host).and_return(nil)
|
217
|
+
|
218
|
+
described_class.new(config).poll_callback(data)
|
219
|
+
expect(config.apm_host).to eq('http://api.airbrake.io')
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -169,7 +169,7 @@ RSpec.describe Airbrake::Config::Validator do
|
|
169
169
|
}
|
170
170
|
end
|
171
171
|
|
172
|
-
it "returns a
|
172
|
+
it "returns a resolved promise" do
|
173
173
|
promise = described_class.check_notify_ability(config)
|
174
174
|
expect(promise).to be_resolved
|
175
175
|
end
|
@@ -180,5 +180,22 @@ RSpec.describe Airbrake::Config::Validator do
|
|
180
180
|
described_class.check_notify_ability(config)
|
181
181
|
end
|
182
182
|
end
|
183
|
+
|
184
|
+
context "when the error_notifications option is false" do
|
185
|
+
let(:config_params) do
|
186
|
+
{
|
187
|
+
project_id: valid_id,
|
188
|
+
project_key: valid_key,
|
189
|
+
error_notifications: false,
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
it "returns a rejected promise" do
|
194
|
+
promise = described_class.check_notify_ability(config)
|
195
|
+
expect(promise.value).to eq(
|
196
|
+
'error' => "error notifications are disabled",
|
197
|
+
)
|
198
|
+
end
|
199
|
+
end
|
183
200
|
end
|
184
201
|
end
|
data/spec/config_spec.rb
CHANGED
@@ -10,19 +10,23 @@ RSpec.describe Airbrake::Config do
|
|
10
10
|
its(:app_version) { is_expected.to be_nil }
|
11
11
|
its(:versions) { is_expected.to be_empty }
|
12
12
|
its(:host) { is_expected.to eq('https://api.airbrake.io') }
|
13
|
-
its(:
|
13
|
+
its(:error_host) { is_expected.to eq('https://api.airbrake.io') }
|
14
|
+
its(:apm_host) { is_expected.to eq('https://api.airbrake.io') }
|
15
|
+
its(:error_endpoint) { is_expected.not_to be_nil }
|
14
16
|
its(:workers) { is_expected.to eq(1) }
|
15
17
|
its(:queue_size) { is_expected.to eq(100) }
|
16
18
|
its(:root_directory) { is_expected.to eq(Bundler.root.realpath.to_s) }
|
17
19
|
its(:environment) { is_expected.to be_nil }
|
18
20
|
its(:ignore_environments) { is_expected.to be_empty }
|
19
21
|
its(:timeout) { is_expected.to be_nil }
|
20
|
-
its(:
|
21
|
-
its(:
|
22
|
+
its(:blocklist_keys) { is_expected.to be_empty }
|
23
|
+
its(:allowlist_keys) { is_expected.to be_empty }
|
22
24
|
its(:performance_stats) { is_expected.to eq(true) }
|
23
25
|
its(:performance_stats_flush_period) { is_expected.to eq(15) }
|
24
26
|
its(:query_stats) { is_expected.to eq(true) }
|
25
27
|
its(:job_stats) { is_expected.to eq(true) }
|
28
|
+
its(:error_notifications) { is_expected.to eq(true) }
|
29
|
+
its(:__remote_configuration) { is_expected.to eq(false) }
|
26
30
|
|
27
31
|
describe "#new" do
|
28
32
|
context "when user config is passed" do
|
@@ -63,13 +67,13 @@ RSpec.describe Airbrake::Config do
|
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
66
|
-
describe "#
|
70
|
+
describe "#error_endpoint" do
|
67
71
|
subject { described_class.new(valid_params.merge(user_config)) }
|
68
72
|
|
69
73
|
context "when host ends with a URL with a slug with a trailing slash" do
|
70
74
|
let(:user_config) { { host: 'https://localhost/bingo/' } }
|
71
75
|
|
72
|
-
its(:
|
76
|
+
its(:error_endpoint) do
|
73
77
|
is_expected.to eq(URI('https://localhost/bingo/api/v3/projects/1/notices'))
|
74
78
|
end
|
75
79
|
end
|
@@ -77,7 +81,7 @@ RSpec.describe Airbrake::Config do
|
|
77
81
|
context "when host ends with a URL with a slug without a trailing slash" do
|
78
82
|
let(:user_config) { { host: 'https://localhost/bingo' } }
|
79
83
|
|
80
|
-
its(:
|
84
|
+
its(:error_endpoint) do
|
81
85
|
is_expected.to eq(URI('https://localhost/api/v3/projects/1/notices'))
|
82
86
|
end
|
83
87
|
end
|
@@ -169,4 +173,32 @@ RSpec.describe Airbrake::Config do
|
|
169
173
|
expect(subject.logger.level).to eq(Logger::WARN)
|
170
174
|
end
|
171
175
|
end
|
176
|
+
|
177
|
+
describe "#blacklist_keys=" do
|
178
|
+
before { allow(Kernel).to receive(:warn) }
|
179
|
+
|
180
|
+
it "sets blocklist_keys instead" do
|
181
|
+
subject.blacklist_keys = [1, 2, 3]
|
182
|
+
expect(subject.blocklist_keys).to eq([1, 2, 3])
|
183
|
+
end
|
184
|
+
|
185
|
+
it "prints a warning" do
|
186
|
+
expect(Kernel).to receive(:warn).with(/use blocklist_keys= instead/)
|
187
|
+
subject.blacklist_keys = [1, 2, 3]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "#whitelist_keys=" do
|
192
|
+
before { allow(Kernel).to receive(:warn) }
|
193
|
+
|
194
|
+
it "sets allowlist_keys instead" do
|
195
|
+
subject.whitelist_keys = [1, 2, 3]
|
196
|
+
expect(subject.allowlist_keys).to eq([1, 2, 3])
|
197
|
+
end
|
198
|
+
|
199
|
+
it "prints a warning" do
|
200
|
+
expect(Kernel).to receive(:warn).with(/use allowlist_keys= instead/)
|
201
|
+
subject.whitelist_keys = [1, 2, 3]
|
202
|
+
end
|
203
|
+
end
|
172
204
|
end
|
data/spec/filter_chain_spec.rb
CHANGED
@@ -89,4 +89,31 @@ RSpec.describe Airbrake::FilterChain do
|
|
89
89
|
expect(subject.inspect).to eq('[Proc]')
|
90
90
|
end
|
91
91
|
end
|
92
|
+
|
93
|
+
describe "#includes?" do
|
94
|
+
context "when a custom filter class is included in the filter chain" do
|
95
|
+
it "returns true" do
|
96
|
+
klass = Class.new {}
|
97
|
+
|
98
|
+
subject.add_filter(klass.new)
|
99
|
+
expect(subject.includes?(klass)).to eq(true)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when Proc filter class is included in the filter chain" do
|
104
|
+
it "returns true" do
|
105
|
+
subject.add_filter(proc {})
|
106
|
+
expect(subject.includes?(Proc)).to eq(true)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when filter class is NOT included in the filter chain" do
|
111
|
+
it "returns false" do
|
112
|
+
klass = Class.new {}
|
113
|
+
|
114
|
+
subject.add_filter(proc {})
|
115
|
+
expect(subject.includes?(klass)).to eq(false)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
92
119
|
end
|
@@ -21,24 +21,41 @@ RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
context "when .git directory exists" do
|
24
|
-
|
24
|
+
context "when AIRBRAKE_DEPLOY_USERNAME env variable is set" do
|
25
|
+
before { ENV['AIRBRAKE_DEPLOY_USERNAME'] = 'deployer' }
|
25
26
|
|
26
|
-
|
27
|
-
|
27
|
+
it "attaches username from the environment" do
|
28
|
+
subject.call(notice)
|
29
|
+
expect(notice[:context][:lastCheckout][:username]).to eq('deployer')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when AIRBRAKE_DEPLOY_USERNAME env variable is NOT set" do
|
34
|
+
before { ENV['AIRBRAKE_DEPLOY_USERNAME'] = nil }
|
35
|
+
|
36
|
+
it "attaches last checkouted username" do
|
37
|
+
subject.call(notice)
|
38
|
+
username = notice[:context][:lastCheckout][:username]
|
39
|
+
expect(username).not_to be_empty
|
40
|
+
expect(username).not_to be_nil
|
41
|
+
end
|
28
42
|
end
|
29
43
|
|
30
44
|
it "attaches last checkouted email" do
|
45
|
+
subject.call(notice)
|
31
46
|
expect(notice[:context][:lastCheckout][:email]).to(
|
32
47
|
match(/\A\w+[\w.-]*@\w+\.?\w+?\z/),
|
33
48
|
)
|
34
49
|
end
|
35
50
|
|
36
51
|
it "attaches last checkouted revision" do
|
52
|
+
subject.call(notice)
|
37
53
|
expect(notice[:context][:lastCheckout][:revision]).not_to be_empty
|
38
54
|
expect(notice[:context][:lastCheckout][:revision].size).to eq(40)
|
39
55
|
end
|
40
56
|
|
41
57
|
it "attaches last checkouted time" do
|
58
|
+
subject.call(notice)
|
42
59
|
expect(notice[:context][:lastCheckout][:time]).not_to be_empty
|
43
60
|
expect(notice[:context][:lastCheckout][:time].size).to eq(25)
|
44
61
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
RSpec.describe Airbrake::Filters::
|
1
|
+
RSpec.describe Airbrake::Filters::KeysAllowlist do
|
2
2
|
subject { described_class.new(patterns) }
|
3
3
|
|
4
4
|
let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
|
@@ -70,10 +70,10 @@ RSpec.describe Airbrake::Filters::KeysWhitelist do
|
|
70
70
|
|
71
71
|
it "logs an error" do
|
72
72
|
expect(Airbrake::Loggable.instance).to receive(:error).with(
|
73
|
-
/
|
73
|
+
/KeysAllowlist is invalid.+patterns: \[#<Object:.+>\]/,
|
74
74
|
)
|
75
|
-
|
76
|
-
|
75
|
+
keys_allowlist = described_class.new(patterns)
|
76
|
+
keys_allowlist.call(notice)
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
@@ -83,10 +83,10 @@ RSpec.describe Airbrake::Filters::KeysWhitelist do
|
|
83
83
|
context "and when the filter is called once" do
|
84
84
|
it "logs an error" do
|
85
85
|
expect(Airbrake::Loggable.instance).to receive(:error).with(
|
86
|
-
/
|
86
|
+
/KeysAllowlist is invalid.+patterns: \[#<Proc:.+>\]/,
|
87
87
|
)
|
88
|
-
|
89
|
-
|
88
|
+
keys_allowlist = described_class.new(patterns)
|
89
|
+
keys_allowlist.call(notice)
|
90
90
|
end
|
91
91
|
|
92
92
|
include_examples(
|
@@ -113,10 +113,10 @@ RSpec.describe Airbrake::Filters::KeysWhitelist do
|
|
113
113
|
|
114
114
|
it "logs an error" do
|
115
115
|
expect(Airbrake::Loggable.instance).to receive(:error).with(
|
116
|
-
/
|
116
|
+
/KeysAllowlist is invalid.+patterns: \[#<Object:.+>\]/,
|
117
117
|
)
|
118
|
-
|
119
|
-
|
118
|
+
keys_allowlist = described_class.new(patterns)
|
119
|
+
keys_allowlist.call(notice)
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|