airbrake-ruby 4.15.0 → 6.0.2
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/async_sender.rb +4 -2
- data/lib/airbrake-ruby/backtrace.rb +6 -5
- data/lib/airbrake-ruby/config/processor.rb +71 -0
- data/lib/airbrake-ruby/config/validator.rb +6 -0
- data/lib/airbrake-ruby/config.rb +44 -35
- data/lib/airbrake-ruby/context.rb +51 -0
- data/lib/airbrake-ruby/file_cache.rb +1 -1
- data/lib/airbrake-ruby/filter_chain.rb +3 -0
- data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
- data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +3 -4
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +4 -1
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +3 -1
- data/lib/airbrake-ruby/filters/keys_filter.rb +23 -15
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +11 -11
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +4 -3
- data/lib/airbrake-ruby/grouppable.rb +1 -1
- data/lib/airbrake-ruby/ignorable.rb +1 -2
- data/lib/airbrake-ruby/mergeable.rb +1 -1
- data/lib/airbrake-ruby/monotonic_time.rb +1 -1
- data/lib/airbrake-ruby/notice.rb +1 -8
- data/lib/airbrake-ruby/notice_notifier.rb +4 -4
- data/lib/airbrake-ruby/performance_breakdown.rb +1 -6
- data/lib/airbrake-ruby/performance_notifier.rb +40 -54
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +1 -6
- data/lib/airbrake-ruby/queue.rb +1 -8
- data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
- data/lib/airbrake-ruby/remote_settings.rb +128 -0
- data/lib/airbrake-ruby/request.rb +1 -8
- data/lib/airbrake-ruby/stat.rb +2 -13
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +12 -9
- data/lib/airbrake-ruby/thread_pool.rb +9 -6
- data/lib/airbrake-ruby/time_truncate.rb +2 -2
- data/lib/airbrake-ruby/timed_trace.rb +1 -3
- data/lib/airbrake-ruby/truncator.rb +8 -2
- data/lib/airbrake-ruby/version.rb +11 -1
- data/lib/airbrake-ruby.rb +44 -54
- data/spec/airbrake_spec.rb +178 -92
- data/spec/async_sender_spec.rb +10 -8
- data/spec/backtrace_spec.rb +39 -36
- data/spec/benchmark_spec.rb +5 -3
- data/spec/code_hunk_spec.rb +26 -17
- data/spec/config/processor_spec.rb +151 -0
- data/spec/config/validator_spec.rb +23 -3
- data/spec/config_spec.rb +40 -52
- data/spec/context_spec.rb +54 -0
- data/spec/deploy_notifier_spec.rb +6 -4
- data/spec/file_cache_spec.rb +1 -0
- data/spec/filter_chain_spec.rb +29 -24
- data/spec/filters/context_filter_spec.rb +14 -5
- data/spec/filters/dependency_filter_spec.rb +3 -1
- data/spec/filters/exception_attributes_filter_spec.rb +5 -3
- data/spec/filters/gem_root_filter_spec.rb +9 -6
- data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
- data/spec/filters/git_repository_filter.rb +9 -9
- data/spec/filters/git_revision_filter_spec.rb +20 -20
- data/spec/filters/keys_allowlist_spec.rb +26 -16
- data/spec/filters/keys_blocklist_spec.rb +35 -18
- data/spec/filters/root_directory_filter_spec.rb +7 -7
- data/spec/filters/sql_filter_spec.rb +28 -28
- data/spec/filters/system_exit_filter_spec.rb +4 -2
- data/spec/filters/thread_filter_spec.rb +16 -14
- data/spec/loggable_spec.rb +2 -2
- data/spec/monotonic_time_spec.rb +8 -6
- data/spec/nested_exception_spec.rb +46 -46
- data/spec/notice_notifier/options_spec.rb +25 -15
- data/spec/notice_notifier_spec.rb +54 -49
- data/spec/notice_spec.rb +7 -3
- data/spec/performance_breakdown_spec.rb +0 -12
- data/spec/performance_notifier_spec.rb +69 -87
- data/spec/promise_spec.rb +38 -32
- data/spec/query_spec.rb +1 -11
- data/spec/queue_spec.rb +1 -13
- data/spec/remote_settings/callback_spec.rb +162 -0
- data/spec/remote_settings/settings_data_spec.rb +348 -0
- data/spec/remote_settings_spec.rb +201 -0
- data/spec/request_spec.rb +1 -13
- data/spec/response_spec.rb +34 -12
- data/spec/spec_helper.rb +4 -4
- data/spec/stashable_spec.rb +5 -5
- data/spec/stat_spec.rb +7 -14
- data/spec/sync_sender_spec.rb +52 -17
- data/spec/tdigest_spec.rb +61 -56
- data/spec/thread_pool_spec.rb +65 -56
- data/spec/time_truncate_spec.rb +23 -6
- data/spec/timed_trace_spec.rb +32 -30
- data/spec/truncator_spec.rb +72 -43
- metadata +66 -50
data/spec/config_spec.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
RSpec.describe Airbrake::Config do
|
2
|
+
subject(:config) { described_class.new }
|
3
|
+
|
2
4
|
let(:resolved_promise) { Airbrake::Promise.new.resolve }
|
3
5
|
let(:rejected_promise) { Airbrake::Promise.new.reject }
|
4
6
|
|
@@ -10,7 +12,9 @@ RSpec.describe Airbrake::Config do
|
|
10
12
|
its(:app_version) { is_expected.to be_nil }
|
11
13
|
its(:versions) { is_expected.to be_empty }
|
12
14
|
its(:host) { is_expected.to eq('https://api.airbrake.io') }
|
13
|
-
its(:
|
15
|
+
its(:error_host) { is_expected.to eq('https://api.airbrake.io') }
|
16
|
+
its(:apm_host) { is_expected.to eq('https://api.airbrake.io') }
|
17
|
+
its(:error_endpoint) { is_expected.not_to be_nil }
|
14
18
|
its(:workers) { is_expected.to eq(1) }
|
15
19
|
its(:queue_size) { is_expected.to eq(100) }
|
16
20
|
its(:root_directory) { is_expected.to eq(Bundler.root.realpath.to_s) }
|
@@ -23,22 +27,32 @@ RSpec.describe Airbrake::Config do
|
|
23
27
|
its(:performance_stats_flush_period) { is_expected.to eq(15) }
|
24
28
|
its(:query_stats) { is_expected.to eq(true) }
|
25
29
|
its(:job_stats) { is_expected.to eq(true) }
|
30
|
+
its(:error_notifications) { is_expected.to eq(true) }
|
31
|
+
its(:remote_config) { is_expected.to eq(true) }
|
32
|
+
|
33
|
+
its(:remote_config_host) do
|
34
|
+
is_expected.to eq('https://notifier-configs.airbrake.io')
|
35
|
+
end
|
26
36
|
|
27
37
|
describe "#new" do
|
28
38
|
context "when user config is passed" do
|
29
39
|
subject { described_class.new(logger: StringIO.new) }
|
40
|
+
|
30
41
|
its(:logger) { is_expected.to be_a(StringIO) }
|
31
42
|
end
|
32
43
|
end
|
33
44
|
|
34
45
|
describe "#valid?" do
|
35
|
-
context "when
|
36
|
-
before
|
46
|
+
context "when the config is valid" do
|
47
|
+
before do
|
48
|
+
config.project_id = 123
|
49
|
+
config.project_key = 'abc'
|
50
|
+
end
|
51
|
+
|
37
52
|
it { is_expected.to be_valid }
|
38
53
|
end
|
39
54
|
|
40
|
-
context "when
|
41
|
-
before { expect(subject).to receive(:validate).and_return(rejected_promise) }
|
55
|
+
context "when the config is invalid" do
|
42
56
|
it { is_expected.not_to be_valid }
|
43
57
|
end
|
44
58
|
end
|
@@ -46,7 +60,7 @@ RSpec.describe Airbrake::Config do
|
|
46
60
|
describe "#ignored_environment?" do
|
47
61
|
context "when Validator returns a resolved promise" do
|
48
62
|
before do
|
49
|
-
|
63
|
+
allow(Airbrake::Config::Validator).to receive(:check_notify_ability)
|
50
64
|
.and_return(resolved_promise)
|
51
65
|
end
|
52
66
|
|
@@ -55,7 +69,7 @@ RSpec.describe Airbrake::Config do
|
|
55
69
|
|
56
70
|
context "when Validator returns a rejected promise" do
|
57
71
|
before do
|
58
|
-
|
72
|
+
allow(Airbrake::Config::Validator).to receive(:check_notify_ability)
|
59
73
|
.and_return(rejected_promise)
|
60
74
|
end
|
61
75
|
|
@@ -63,13 +77,13 @@ RSpec.describe Airbrake::Config do
|
|
63
77
|
end
|
64
78
|
end
|
65
79
|
|
66
|
-
describe "#
|
80
|
+
describe "#error_endpoint" do
|
67
81
|
subject { described_class.new(valid_params.merge(user_config)) }
|
68
82
|
|
69
83
|
context "when host ends with a URL with a slug with a trailing slash" do
|
70
84
|
let(:user_config) { { host: 'https://localhost/bingo/' } }
|
71
85
|
|
72
|
-
its(:
|
86
|
+
its(:error_endpoint) do
|
73
87
|
is_expected.to eq(URI('https://localhost/bingo/api/v3/projects/1/notices'))
|
74
88
|
end
|
75
89
|
end
|
@@ -77,7 +91,7 @@ RSpec.describe Airbrake::Config do
|
|
77
91
|
context "when host ends with a URL with a slug without a trailing slash" do
|
78
92
|
let(:user_config) { { host: 'https://localhost/bingo' } }
|
79
93
|
|
80
|
-
its(:
|
94
|
+
its(:error_endpoint) do
|
81
95
|
is_expected.to eq(URI('https://localhost/api/v3/projects/1/notices'))
|
82
96
|
end
|
83
97
|
end
|
@@ -88,19 +102,21 @@ RSpec.describe Airbrake::Config do
|
|
88
102
|
end
|
89
103
|
|
90
104
|
describe "#check_configuration" do
|
91
|
-
let(:user_config) { {} }
|
92
|
-
|
93
105
|
subject { described_class.new(valid_params.merge(user_config)) }
|
94
106
|
|
107
|
+
let(:user_config) { {} }
|
108
|
+
|
95
109
|
its(:check_configuration) { is_expected.to be_an(Airbrake::Promise) }
|
96
110
|
|
97
111
|
context "when config is invalid" do
|
98
112
|
let(:user_config) { { project_id: nil } }
|
113
|
+
|
99
114
|
its(:check_configuration) { is_expected.to be_rejected }
|
100
115
|
end
|
101
116
|
|
102
117
|
context "when current environment is ignored" do
|
103
118
|
let(:user_config) { { environment: 'test', ignore_environments: ['test'] } }
|
119
|
+
|
104
120
|
its(:check_configuration) { is_expected.to be_rejected }
|
105
121
|
end
|
106
122
|
|
@@ -111,22 +127,22 @@ RSpec.describe Airbrake::Config do
|
|
111
127
|
|
112
128
|
describe "#check_performance_options" do
|
113
129
|
it "returns a promise" do
|
114
|
-
|
115
|
-
expect(
|
130
|
+
metric = Airbrake::Query.new(method: '', route: '', query: '', timing: 1)
|
131
|
+
expect(config.check_performance_options(metric))
|
116
132
|
.to be_an(Airbrake::Promise)
|
117
133
|
end
|
118
134
|
|
119
135
|
context "when performance stats are disabled" do
|
120
|
-
before {
|
136
|
+
before { config.performance_stats = false }
|
121
137
|
|
122
|
-
let(:
|
138
|
+
let(:metric) do
|
123
139
|
Airbrake::Request.new(
|
124
140
|
method: 'GET', route: '/foo', status_code: 200, timing: 1,
|
125
141
|
)
|
126
142
|
end
|
127
143
|
|
128
144
|
it "returns a rejected promise" do
|
129
|
-
promise =
|
145
|
+
promise = config.check_performance_options(metric)
|
130
146
|
expect(promise.value).to eq(
|
131
147
|
'error' => "The Performance Stats feature is disabled",
|
132
148
|
)
|
@@ -134,14 +150,14 @@ RSpec.describe Airbrake::Config do
|
|
134
150
|
end
|
135
151
|
|
136
152
|
context "when query stats are disabled" do
|
137
|
-
before {
|
153
|
+
before { config.query_stats = false }
|
138
154
|
|
139
|
-
let(:
|
155
|
+
let(:metric) do
|
140
156
|
Airbrake::Query.new(method: 'GET', route: '/foo', query: '', timing: 1)
|
141
157
|
end
|
142
158
|
|
143
159
|
it "returns a rejected promise" do
|
144
|
-
promise =
|
160
|
+
promise = config.check_performance_options(metric)
|
145
161
|
expect(promise.value).to eq(
|
146
162
|
'error' => "The Query Stats feature is disabled",
|
147
163
|
)
|
@@ -149,14 +165,14 @@ RSpec.describe Airbrake::Config do
|
|
149
165
|
end
|
150
166
|
|
151
167
|
context "when job stats are disabled" do
|
152
|
-
before {
|
168
|
+
before { config.job_stats = false }
|
153
169
|
|
154
|
-
let(:
|
170
|
+
let(:metric) do
|
155
171
|
Airbrake::Queue.new(queue: 'foo_queue', error_count: 0, timing: 1)
|
156
172
|
end
|
157
173
|
|
158
174
|
it "returns a rejected promise" do
|
159
|
-
promise =
|
175
|
+
promise = config.check_performance_options(metric)
|
160
176
|
expect(promise.value).to eq(
|
161
177
|
'error' => "The Job Stats feature is disabled",
|
162
178
|
)
|
@@ -166,35 +182,7 @@ RSpec.describe Airbrake::Config do
|
|
166
182
|
|
167
183
|
describe "#logger" do
|
168
184
|
it "sets logger level to Logger::WARN" do
|
169
|
-
expect(
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe "#blacklist_keys=" do
|
174
|
-
before { allow(Kernel).to receive(:warn) }
|
175
|
-
|
176
|
-
it "sets blocklist_keys instead" do
|
177
|
-
subject.blacklist_keys = [1, 2, 3]
|
178
|
-
expect(subject.blocklist_keys).to eq([1, 2, 3])
|
179
|
-
end
|
180
|
-
|
181
|
-
it "prints a warning" do
|
182
|
-
expect(Kernel).to receive(:warn).with(/use blocklist_keys= instead/)
|
183
|
-
subject.blacklist_keys = [1, 2, 3]
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
describe "#whitelist_keys=" do
|
188
|
-
before { allow(Kernel).to receive(:warn) }
|
189
|
-
|
190
|
-
it "sets allowlist_keys instead" do
|
191
|
-
subject.whitelist_keys = [1, 2, 3]
|
192
|
-
expect(subject.allowlist_keys).to eq([1, 2, 3])
|
193
|
-
end
|
194
|
-
|
195
|
-
it "prints a warning" do
|
196
|
-
expect(Kernel).to receive(:warn).with(/use allowlist_keys= instead/)
|
197
|
-
subject.whitelist_keys = [1, 2, 3]
|
185
|
+
expect(config.logger.level).to eq(Logger::WARN)
|
198
186
|
end
|
199
187
|
end
|
200
188
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
RSpec.describe Airbrake::Context do
|
2
|
+
subject(:context) { described_class.current }
|
3
|
+
|
4
|
+
before { described_class.current.clear }
|
5
|
+
|
6
|
+
after { described_class.current.clear }
|
7
|
+
|
8
|
+
describe "#merge!" do
|
9
|
+
it "merges the given context with the current one" do
|
10
|
+
context.merge!(apples: 'oranges')
|
11
|
+
expect(context.to_h).to match(apples: 'oranges')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#clear" do
|
16
|
+
it "clears the context" do
|
17
|
+
context.merge!(apples: 'oranges')
|
18
|
+
context.clear
|
19
|
+
expect(context.to_h).to be_empty
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#to_h" do
|
24
|
+
it "returns a hash representation of the context" do
|
25
|
+
expect(context.to_h).to be_a(Hash)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#empty?" do
|
30
|
+
context "when the context has data" do
|
31
|
+
it "returns true" do
|
32
|
+
context.merge!(apples: 'oranges')
|
33
|
+
expect(context).not_to be_empty
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when the context has NO data" do
|
38
|
+
it "returns false" do
|
39
|
+
expect(context).to be_empty
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when another thread is spawned" do
|
45
|
+
it "doesn't clash with other threads' contexts" do
|
46
|
+
described_class.current.merge!(apples: 'oranges')
|
47
|
+
th = Thread.new do
|
48
|
+
described_class.current.merge!(foos: 'bars')
|
49
|
+
end
|
50
|
+
th.join
|
51
|
+
expect(described_class.current.to_h).to match(apples: 'oranges')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -4,17 +4,19 @@ RSpec.describe Airbrake::DeployNotifier do
|
|
4
4
|
end
|
5
5
|
|
6
6
|
describe "#notify" do
|
7
|
+
subject(:deploy_notifier) { described_class.new }
|
8
|
+
|
7
9
|
it "returns a promise" do
|
8
10
|
stub_request(:post, 'https://api.airbrake.io/api/v4/projects/1/deploys')
|
9
11
|
.to_return(status: 201, body: '{}')
|
10
|
-
expect(
|
12
|
+
expect(deploy_notifier.notify({})).to be_an(Airbrake::Promise)
|
11
13
|
end
|
12
14
|
|
13
15
|
context "when config is invalid" do
|
14
16
|
before { Airbrake::Config.instance.merge(project_id: nil) }
|
15
17
|
|
16
18
|
it "returns a rejected promise" do
|
17
|
-
promise =
|
19
|
+
promise = deploy_notifier.notify({})
|
18
20
|
expect(promise).to be_rejected
|
19
21
|
end
|
20
22
|
end
|
@@ -28,7 +30,7 @@ RSpec.describe Airbrake::DeployNotifier do
|
|
28
30
|
instance_of(Airbrake::Promise),
|
29
31
|
URI('https://api.airbrake.io/api/v4/projects/1/deploys'),
|
30
32
|
)
|
31
|
-
|
33
|
+
deploy_notifier.notify(environment: 'barenv')
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -41,7 +43,7 @@ RSpec.describe Airbrake::DeployNotifier do
|
|
41
43
|
instance_of(Airbrake::Promise),
|
42
44
|
URI('https://api.airbrake.io/api/v4/projects/1/deploys'),
|
43
45
|
)
|
44
|
-
|
46
|
+
deploy_notifier.notify({})
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
data/spec/file_cache_spec.rb
CHANGED
data/spec/filter_chain_spec.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
RSpec.describe Airbrake::FilterChain do
|
2
|
+
subject(:filter_chain) { described_class.new }
|
3
|
+
|
2
4
|
let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
|
3
5
|
|
4
6
|
describe "#refine" do
|
@@ -19,24 +21,27 @@ RSpec.describe Airbrake::FilterChain do
|
|
19
21
|
it "executes filters from heaviest to lightest" do
|
20
22
|
notice[:params][:bingo] = []
|
21
23
|
|
22
|
-
(0...3).reverse_each { |i|
|
23
|
-
|
24
|
+
(0...3).reverse_each { |i| filter_chain.add_filter(filter.new(i)) }
|
25
|
+
filter_chain.refine(notice)
|
24
26
|
|
25
27
|
expect(notice[:params][:bingo]).to eq([2, 1, 0])
|
26
28
|
end
|
27
29
|
|
28
30
|
it "stops execution once a notice was ignored" do
|
29
31
|
f2 = filter.new(2)
|
30
|
-
|
32
|
+
allow(f2).to receive(:call)
|
31
33
|
|
32
34
|
f1 = proc { |notice| notice.ignore! }
|
33
35
|
|
34
36
|
f0 = filter.new(-1)
|
35
|
-
|
37
|
+
allow(f0).to receive(:call)
|
38
|
+
|
39
|
+
[f2, f1, f0].each { |f| filter_chain.add_filter(f) }
|
36
40
|
|
37
|
-
|
41
|
+
filter_chain.refine(notice)
|
38
42
|
|
39
|
-
|
43
|
+
expect(f2).to have_received(:call)
|
44
|
+
expect(f0).not_to have_received(:call)
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
@@ -63,56 +68,56 @@ RSpec.describe Airbrake::FilterChain do
|
|
63
68
|
notice[:params][:foo] = []
|
64
69
|
|
65
70
|
f1 = filter.new(1)
|
66
|
-
|
71
|
+
filter_chain.add_filter(f1)
|
67
72
|
|
68
73
|
foo_filter_mock = double
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
74
|
+
allow(foo_filter_mock).to receive(:name).at_least(:once).and_return('FooFilter')
|
75
|
+
filter_chain.delete_filter(foo_filter_mock)
|
76
|
+
|
77
|
+
expect(foo_filter_mock).to have_received(:name)
|
73
78
|
|
74
79
|
f2 = filter.new(2)
|
75
|
-
|
80
|
+
filter_chain.add_filter(f2)
|
76
81
|
|
77
|
-
|
82
|
+
filter_chain.refine(notice)
|
78
83
|
expect(notice[:params][:foo]).to eq([2])
|
79
84
|
end
|
80
85
|
end
|
81
86
|
|
82
87
|
describe "#inspect" do
|
83
88
|
it "returns a string representation of an empty FilterChain" do
|
84
|
-
expect(
|
89
|
+
expect(filter_chain.inspect).to eq('[]')
|
85
90
|
end
|
86
91
|
|
87
92
|
it "returns a string representation of a non-empty FilterChain" do
|
88
|
-
|
89
|
-
expect(
|
93
|
+
filter_chain.add_filter(proc {})
|
94
|
+
expect(filter_chain.inspect).to eq('[Proc]')
|
90
95
|
end
|
91
96
|
end
|
92
97
|
|
93
98
|
describe "#includes?" do
|
94
99
|
context "when a custom filter class is included in the filter chain" do
|
95
100
|
it "returns true" do
|
96
|
-
klass = Class.new
|
101
|
+
klass = Class.new
|
97
102
|
|
98
|
-
|
99
|
-
expect(
|
103
|
+
filter_chain.add_filter(klass.new)
|
104
|
+
expect(filter_chain.includes?(klass)).to eq(true)
|
100
105
|
end
|
101
106
|
end
|
102
107
|
|
103
108
|
context "when Proc filter class is included in the filter chain" do
|
104
109
|
it "returns true" do
|
105
|
-
|
106
|
-
expect(
|
110
|
+
filter_chain.add_filter(proc {})
|
111
|
+
expect(filter_chain.includes?(Proc)).to eq(true)
|
107
112
|
end
|
108
113
|
end
|
109
114
|
|
110
115
|
context "when filter class is NOT included in the filter chain" do
|
111
116
|
it "returns false" do
|
112
|
-
klass = Class.new
|
117
|
+
klass = Class.new
|
113
118
|
|
114
|
-
|
115
|
-
expect(
|
119
|
+
filter_chain.add_filter(proc {})
|
120
|
+
expect(filter_chain.includes?(klass)).to eq(false)
|
116
121
|
end
|
117
122
|
end
|
118
123
|
end
|
@@ -3,21 +3,30 @@ RSpec.describe Airbrake::Filters::ContextFilter do
|
|
3
3
|
|
4
4
|
context "when the current context is empty" do
|
5
5
|
it "doesn't merge anything with params" do
|
6
|
-
described_class.new
|
6
|
+
described_class.new.call(notice)
|
7
7
|
expect(notice[:params]).to be_empty
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
context "when the current context has some data" do
|
12
12
|
it "merges the data with params" do
|
13
|
-
|
13
|
+
Airbrake.merge_context(apples: 'oranges')
|
14
|
+
described_class.new.call(notice)
|
14
15
|
expect(notice[:params]).to eq(airbrake_context: { apples: 'oranges' })
|
15
16
|
end
|
16
17
|
|
17
|
-
it "clears the data from the
|
18
|
+
it "clears the data from the current context" do
|
18
19
|
context = { apples: 'oranges' }
|
19
|
-
|
20
|
-
|
20
|
+
Airbrake.merge_context(context)
|
21
|
+
described_class.new.call(notice)
|
22
|
+
expect(Airbrake::Context.current).to be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
it "does not mutate the provided context object" do
|
26
|
+
context = { apples: 'oranges' }
|
27
|
+
Airbrake.merge_context(context)
|
28
|
+
described_class.new.call(notice)
|
29
|
+
expect(context).to match(apples: 'oranges')
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
RSpec.describe Airbrake::Filters::DependencyFilter do
|
2
|
+
subject(:dependency_filter) { described_class.new }
|
3
|
+
|
2
4
|
let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
|
3
5
|
|
4
6
|
describe "#call" do
|
5
7
|
it "attaches loaded dependencies to context/versions/dependencies" do
|
6
|
-
|
8
|
+
dependency_filter.call(notice)
|
7
9
|
expect(notice[:context][:versions][:dependencies]).to include(
|
8
10
|
'airbrake-ruby' => Airbrake::AIRBRAKE_RUBY_VERSION,
|
9
11
|
)
|
@@ -1,4 +1,6 @@
|
|
1
1
|
RSpec.describe Airbrake::Filters::ExceptionAttributesFilter do
|
2
|
+
subject(:exception_attributes_filter) { described_class.new }
|
3
|
+
|
2
4
|
describe "#call" do
|
3
5
|
let(:notice) { Airbrake::Notice.new(ex) }
|
4
6
|
|
@@ -12,7 +14,7 @@ RSpec.describe Airbrake::Filters::ExceptionAttributesFilter do
|
|
12
14
|
end
|
13
15
|
|
14
16
|
it "doesn't raise" do
|
15
|
-
expect {
|
17
|
+
expect { exception_attributes_filter.call(notice) }.not_to raise_error
|
16
18
|
expect(notice[:params]).to be_empty
|
17
19
|
end
|
18
20
|
end
|
@@ -27,7 +29,7 @@ RSpec.describe Airbrake::Filters::ExceptionAttributesFilter do
|
|
27
29
|
end
|
28
30
|
|
29
31
|
it "doesn't raise" do
|
30
|
-
expect {
|
32
|
+
expect { exception_attributes_filter.call(notice) }.not_to raise_error
|
31
33
|
expect(notice[:params]).to be_empty
|
32
34
|
end
|
33
35
|
end
|
@@ -42,7 +44,7 @@ RSpec.describe Airbrake::Filters::ExceptionAttributesFilter do
|
|
42
44
|
end
|
43
45
|
|
44
46
|
it "merges parameters with the notice" do
|
45
|
-
|
47
|
+
exception_attributes_filter.call(notice)
|
46
48
|
expect(notice[:params]).to eq(foo: '1')
|
47
49
|
end
|
48
50
|
end
|
@@ -1,24 +1,27 @@
|
|
1
1
|
RSpec.describe Airbrake::Filters::GemRootFilter do
|
2
|
+
subject(:gem_root_filter) { described_class.new }
|
3
|
+
|
2
4
|
let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
|
3
5
|
let(:root1) { '/my/gem/root' }
|
4
6
|
let(:root2) { '/my/other/gem/root' }
|
5
7
|
|
6
8
|
before { Gem.path << root1 << root2 }
|
9
|
+
|
7
10
|
after { 2.times { Gem.path.pop } }
|
8
11
|
|
9
12
|
it "replaces gem root in the backtrace with a label" do
|
10
|
-
# rubocop:disable
|
13
|
+
# rubocop:disable Layout/LineLength
|
11
14
|
notice[:errors].first[:backtrace] = [
|
12
15
|
{ file: "/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb" },
|
13
16
|
{ file: "#{root1}/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb" },
|
14
17
|
{ file: "/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb" },
|
15
18
|
{ file: "#{root2}/gems/rspec-core-3.3.2/exe/rspec" },
|
16
19
|
]
|
17
|
-
# rubocop:enable
|
20
|
+
# rubocop:enable Layout/LineLength
|
18
21
|
|
19
|
-
|
22
|
+
gem_root_filter.call(notice)
|
20
23
|
|
21
|
-
# rubocop:disable
|
24
|
+
# rubocop:disable Layout/LineLength
|
22
25
|
expect(notice[:errors].first[:backtrace]).to(
|
23
26
|
eq(
|
24
27
|
[
|
@@ -29,12 +32,12 @@ RSpec.describe Airbrake::Filters::GemRootFilter do
|
|
29
32
|
],
|
30
33
|
),
|
31
34
|
)
|
32
|
-
# rubocop:enable
|
35
|
+
# rubocop:enable Layout/LineLength
|
33
36
|
end
|
34
37
|
|
35
38
|
it "does not filter file when it is nil" do
|
36
39
|
expect(notice[:errors].first[:file]).to be_nil
|
37
|
-
expect {
|
40
|
+
expect { gem_root_filter.call(notice) }.not_to(
|
38
41
|
change { notice[:errors].first[:file] },
|
39
42
|
)
|
40
43
|
end
|
@@ -1,21 +1,21 @@
|
|
1
1
|
RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
|
2
|
-
subject { described_class.new('.') }
|
2
|
+
subject(:git_last_checkout_filter) { described_class.new('.') }
|
3
3
|
|
4
4
|
let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
|
5
5
|
|
6
6
|
context "when context/lastCheckout is defined" do
|
7
7
|
it "doesn't attach anything to context/lastCheckout" do
|
8
8
|
notice[:context][:lastCheckout] = '123'
|
9
|
-
|
9
|
+
git_last_checkout_filter.call(notice)
|
10
10
|
expect(notice[:context][:lastCheckout]).to eq('123')
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
context "when .git directory doesn't exist" do
|
15
|
-
subject { described_class.new('root/dir') }
|
15
|
+
subject(:git_last_checkout_without_git_dir_filter) { described_class.new('root/dir') }
|
16
16
|
|
17
17
|
it "doesn't attach anything to context/lastCheckout" do
|
18
|
-
|
18
|
+
git_last_checkout_without_git_dir_filter.call(notice)
|
19
19
|
expect(notice[:context][:lastCheckout]).to be_nil
|
20
20
|
end
|
21
21
|
end
|
@@ -25,7 +25,7 @@ RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
|
|
25
25
|
before { ENV['AIRBRAKE_DEPLOY_USERNAME'] = 'deployer' }
|
26
26
|
|
27
27
|
it "attaches username from the environment" do
|
28
|
-
|
28
|
+
git_last_checkout_filter.call(notice)
|
29
29
|
expect(notice[:context][:lastCheckout][:username]).to eq('deployer')
|
30
30
|
end
|
31
31
|
end
|
@@ -34,7 +34,7 @@ RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
|
|
34
34
|
before { ENV['AIRBRAKE_DEPLOY_USERNAME'] = nil }
|
35
35
|
|
36
36
|
it "attaches last checkouted username" do
|
37
|
-
|
37
|
+
git_last_checkout_filter.call(notice)
|
38
38
|
username = notice[:context][:lastCheckout][:username]
|
39
39
|
expect(username).not_to be_empty
|
40
40
|
expect(username).not_to be_nil
|
@@ -42,20 +42,18 @@ RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it "attaches last checkouted email" do
|
45
|
-
|
46
|
-
expect(notice[:context][:lastCheckout][:email]).to(
|
47
|
-
match(/\A\w+[\w.-]*@\w+\.?\w+?\z/),
|
48
|
-
)
|
45
|
+
git_last_checkout_filter.call(notice)
|
46
|
+
expect(notice[:context][:lastCheckout][:email]).to(match(/\A\w+@[\w\-.]+\z/))
|
49
47
|
end
|
50
48
|
|
51
49
|
it "attaches last checkouted revision" do
|
52
|
-
|
50
|
+
git_last_checkout_filter.call(notice)
|
53
51
|
expect(notice[:context][:lastCheckout][:revision]).not_to be_empty
|
54
52
|
expect(notice[:context][:lastCheckout][:revision].size).to eq(40)
|
55
53
|
end
|
56
54
|
|
57
55
|
it "attaches last checkouted time" do
|
58
|
-
|
56
|
+
git_last_checkout_filter.call(notice)
|
59
57
|
expect(notice[:context][:lastCheckout][:time]).not_to be_empty
|
60
58
|
expect(notice[:context][:lastCheckout][:time].size).to eq(25)
|
61
59
|
end
|