airbrake-ruby 4.6.0 → 6.2.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 +5 -5
- data/lib/airbrake-ruby/async_sender.rb +24 -109
- data/lib/airbrake-ruby/backlog.rb +123 -0
- data/lib/airbrake-ruby/backtrace.rb +8 -7
- data/lib/airbrake-ruby/benchmark.rb +1 -1
- data/lib/airbrake-ruby/code_hunk.rb +1 -1
- data/lib/airbrake-ruby/config/processor.rb +77 -0
- data/lib/airbrake-ruby/config/validator.rb +9 -3
- data/lib/airbrake-ruby/config.rb +78 -19
- data/lib/airbrake-ruby/context.rb +51 -0
- data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
- data/lib/airbrake-ruby/file_cache.rb +6 -0
- data/lib/airbrake-ruby/filter_chain.rb +18 -1
- 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 +3 -3
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +7 -7
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +11 -2
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +3 -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 +41 -22
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +35 -11
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +6 -5
- data/lib/airbrake-ruby/grouppable.rb +12 -0
- data/lib/airbrake-ruby/ignorable.rb +1 -2
- data/lib/airbrake-ruby/inspectable.rb +2 -2
- data/lib/airbrake-ruby/loggable.rb +1 -1
- data/lib/airbrake-ruby/mergeable.rb +12 -0
- data/lib/airbrake-ruby/monotonic_time.rb +6 -1
- data/lib/airbrake-ruby/nested_exception.rb +22 -1
- data/lib/airbrake-ruby/notice.rb +12 -17
- data/lib/airbrake-ruby/notice_notifier.rb +15 -7
- data/lib/airbrake-ruby/performance_breakdown.rb +16 -9
- data/lib/airbrake-ruby/performance_notifier.rb +106 -54
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +20 -14
- data/lib/airbrake-ruby/queue.rb +65 -0
- 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 +14 -11
- data/lib/airbrake-ruby/response.rb +56 -5
- data/lib/airbrake-ruby/stat.rb +27 -34
- data/lib/airbrake-ruby/sync_sender.rb +43 -11
- data/lib/airbrake-ruby/tdigest.rb +52 -66
- data/lib/airbrake-ruby/thread_pool.rb +139 -0
- data/lib/airbrake-ruby/time_truncate.rb +2 -2
- data/lib/airbrake-ruby/timed_trace.rb +1 -3
- data/lib/airbrake-ruby/truncator.rb +10 -4
- data/lib/airbrake-ruby/version.rb +11 -1
- data/lib/airbrake-ruby.rb +157 -78
- metadata +122 -116
- data/spec/airbrake_spec.rb +0 -324
- data/spec/async_sender_spec.rb +0 -155
- data/spec/backtrace_spec.rb +0 -427
- data/spec/benchmark_spec.rb +0 -33
- data/spec/code_hunk_spec.rb +0 -115
- data/spec/config/validator_spec.rb +0 -184
- data/spec/config_spec.rb +0 -154
- data/spec/deploy_notifier_spec.rb +0 -48
- data/spec/file_cache.rb +0 -36
- data/spec/filter_chain_spec.rb +0 -92
- data/spec/filters/context_filter_spec.rb +0 -23
- data/spec/filters/dependency_filter_spec.rb +0 -12
- data/spec/filters/exception_attributes_filter_spec.rb +0 -50
- data/spec/filters/gem_root_filter_spec.rb +0 -41
- data/spec/filters/git_last_checkout_filter_spec.rb +0 -46
- data/spec/filters/git_repository_filter.rb +0 -61
- data/spec/filters/git_revision_filter_spec.rb +0 -126
- data/spec/filters/keys_blacklist_spec.rb +0 -225
- data/spec/filters/keys_whitelist_spec.rb +0 -194
- data/spec/filters/root_directory_filter_spec.rb +0 -39
- data/spec/filters/sql_filter_spec.rb +0 -219
- data/spec/filters/system_exit_filter_spec.rb +0 -14
- data/spec/filters/thread_filter_spec.rb +0 -277
- data/spec/fixtures/notroot.txt +0 -7
- data/spec/fixtures/project_root/code.rb +0 -221
- data/spec/fixtures/project_root/empty_file.rb +0 -0
- data/spec/fixtures/project_root/long_line.txt +0 -1
- data/spec/fixtures/project_root/short_file.rb +0 -3
- data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +0 -5
- data/spec/helpers.rb +0 -9
- data/spec/ignorable_spec.rb +0 -14
- data/spec/inspectable_spec.rb +0 -45
- data/spec/monotonic_time_spec.rb +0 -12
- data/spec/nested_exception_spec.rb +0 -73
- data/spec/notice_notifier_spec/options_spec.rb +0 -259
- data/spec/notice_notifier_spec.rb +0 -356
- data/spec/notice_spec.rb +0 -296
- data/spec/performance_breakdown_spec.rb +0 -12
- data/spec/performance_notifier_spec.rb +0 -435
- data/spec/promise_spec.rb +0 -197
- data/spec/query_spec.rb +0 -11
- data/spec/request_spec.rb +0 -11
- data/spec/response_spec.rb +0 -88
- data/spec/spec_helper.rb +0 -100
- data/spec/stashable_spec.rb +0 -23
- data/spec/stat_spec.rb +0 -47
- data/spec/sync_sender_spec.rb +0 -133
- data/spec/tdigest_spec.rb +0 -230
- data/spec/time_truncate_spec.rb +0 -13
- data/spec/timed_trace_spec.rb +0 -125
- data/spec/truncator_spec.rb +0 -238
data/spec/timed_trace_spec.rb
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
RSpec.describe Airbrake::TimedTrace do
|
|
2
|
-
describe ".span" do
|
|
3
|
-
it "returns a timed trace" do
|
|
4
|
-
expect(described_class.span('operation') {}).to be_a(described_class)
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
it "returns a timed trace with a stopped span" do
|
|
8
|
-
timed_trace = described_class.span('operation') {}
|
|
9
|
-
expect(timed_trace.spans).to match('operation' => be > 0)
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe "#span" do
|
|
14
|
-
it "captures a span" do
|
|
15
|
-
subject.span('operation') {}
|
|
16
|
-
expect(subject.spans).to match('operation' => be > 0)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
describe "#start_span" do
|
|
21
|
-
context "when called once" do
|
|
22
|
-
it "returns true" do
|
|
23
|
-
expect(subject.start_span('operation')).to eq(true)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
context "when called multiple times" do
|
|
28
|
-
before { subject.start_span('operation') }
|
|
29
|
-
|
|
30
|
-
it "returns false" do
|
|
31
|
-
expect(subject.start_span('operation')).to eq(false)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
context "when another span was started" do
|
|
36
|
-
before { subject.start_span('operation') }
|
|
37
|
-
|
|
38
|
-
it "returns true" do
|
|
39
|
-
expect(subject.start_span('another operation')).to eq(true)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
context "when #spans was called" do
|
|
44
|
-
before { subject.start_span('operation') }
|
|
45
|
-
|
|
46
|
-
it "returns spans with zero values" do
|
|
47
|
-
expect(subject.spans).to eq('operation' => 0.0)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
describe "#stop_span" do
|
|
53
|
-
context "when #start_span wasn't invoked" do
|
|
54
|
-
it "returns false" do
|
|
55
|
-
expect(subject.stop_span('operation')).to eq(false)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
context "when #start_span was invoked" do
|
|
60
|
-
before { subject.start_span('operation') }
|
|
61
|
-
|
|
62
|
-
it "returns true" do
|
|
63
|
-
expect(subject.stop_span('operation')).to eq(true)
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
context "when multiple spans were started" do
|
|
68
|
-
before do
|
|
69
|
-
subject.start_span('operation')
|
|
70
|
-
subject.start_span('another operation')
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
context "and when stopping in LIFO order" do
|
|
74
|
-
it "returns true for all spans" do
|
|
75
|
-
expect(subject.stop_span('another operation')).to eq(true)
|
|
76
|
-
expect(subject.stop_span('operation')).to eq(true)
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
context "and when stopping in FIFO order" do
|
|
81
|
-
it "returns true for all spans" do
|
|
82
|
-
expect(subject.stop_span('operation')).to eq(true)
|
|
83
|
-
expect(subject.stop_span('another operation')).to eq(true)
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
describe "#spans" do
|
|
90
|
-
context "when no spans were captured" do
|
|
91
|
-
it "returns an empty hash" do
|
|
92
|
-
expect(subject.spans).to eq({})
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
context "when a span was captured" do
|
|
97
|
-
before do
|
|
98
|
-
subject.start_span('operation')
|
|
99
|
-
subject.stop_span('operation')
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
it "returns a Hash with the corresponding span" do
|
|
103
|
-
subject.stop_span('operation')
|
|
104
|
-
expect(subject.spans).to match('operation' => be > 0)
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
context "when multiple spans were captured" do
|
|
109
|
-
before do
|
|
110
|
-
subject.start_span('operation')
|
|
111
|
-
subject.stop_span('operation')
|
|
112
|
-
|
|
113
|
-
subject.start_span('another operation')
|
|
114
|
-
subject.stop_span('another operation')
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
it "returns a Hash with all spans" do
|
|
118
|
-
expect(subject.spans).to match(
|
|
119
|
-
'operation' => be > 0,
|
|
120
|
-
'another operation' => be > 0
|
|
121
|
-
)
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
data/spec/truncator_spec.rb
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
RSpec.describe Airbrake::Truncator do
|
|
2
|
-
def multiply_by_2_max_len(chr)
|
|
3
|
-
chr * 2 * max_len
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
describe "#truncate" do
|
|
7
|
-
let(:max_size) { 3 }
|
|
8
|
-
let(:truncated) { '[Truncated]' }
|
|
9
|
-
let(:max_len) { max_size + truncated.length }
|
|
10
|
-
|
|
11
|
-
subject { described_class.new(max_size).truncate(object) }
|
|
12
|
-
|
|
13
|
-
context "given a frozen string" do
|
|
14
|
-
let(:object) { multiply_by_2_max_len('a') }
|
|
15
|
-
|
|
16
|
-
it "returns a new truncated frozen string" do
|
|
17
|
-
expect(subject.length).to eq(max_len)
|
|
18
|
-
expect(subject).to be_frozen
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
context "given a frozen hash of strings" do
|
|
23
|
-
let(:object) do
|
|
24
|
-
{
|
|
25
|
-
banana: multiply_by_2_max_len('a'),
|
|
26
|
-
kiwi: multiply_by_2_max_len('b'),
|
|
27
|
-
strawberry: 'c',
|
|
28
|
-
shrimp: 'd'
|
|
29
|
-
}.freeze
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it "returns a new truncated frozen hash" do
|
|
33
|
-
expect(subject.size).to eq(max_size)
|
|
34
|
-
expect(subject).to be_frozen
|
|
35
|
-
|
|
36
|
-
expect(subject).to eq(
|
|
37
|
-
banana: 'aaa[Truncated]', kiwi: 'bbb[Truncated]', strawberry: 'c'
|
|
38
|
-
)
|
|
39
|
-
expect(subject[:banana]).to be_frozen
|
|
40
|
-
expect(subject[:kiwi]).to be_frozen
|
|
41
|
-
expect(subject[:strawberry]).not_to be_frozen
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
context "given a frozen array of strings" do
|
|
46
|
-
let(:object) do
|
|
47
|
-
[
|
|
48
|
-
multiply_by_2_max_len('a'),
|
|
49
|
-
'b',
|
|
50
|
-
multiply_by_2_max_len('c'),
|
|
51
|
-
'd'
|
|
52
|
-
].freeze
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it "returns a new truncated frozen array" do
|
|
56
|
-
expect(subject.size).to eq(max_size)
|
|
57
|
-
expect(subject).to be_frozen
|
|
58
|
-
|
|
59
|
-
expect(subject).to eq(['aaa[Truncated]', 'b', 'ccc[Truncated]'])
|
|
60
|
-
expect(subject[0]).to be_frozen
|
|
61
|
-
expect(subject[1]).not_to be_frozen
|
|
62
|
-
expect(subject[2]).to be_frozen
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
context "given a frozen set of strings" do
|
|
67
|
-
let(:object) do
|
|
68
|
-
Set.new([
|
|
69
|
-
multiply_by_2_max_len('a'),
|
|
70
|
-
'b',
|
|
71
|
-
multiply_by_2_max_len('c'),
|
|
72
|
-
'd'
|
|
73
|
-
]).freeze
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it "returns a new truncated frozen array" do
|
|
77
|
-
expect(subject.size).to eq(max_size)
|
|
78
|
-
expect(subject).to be_frozen
|
|
79
|
-
|
|
80
|
-
expect(subject).to eq(
|
|
81
|
-
Set.new(['aaa[Truncated]', 'b', 'ccc[Truncated]'])
|
|
82
|
-
)
|
|
83
|
-
expect(subject).to be_frozen
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
context "given an arbitrary frozen object that responds to #to_json" do
|
|
88
|
-
let(:object) do
|
|
89
|
-
obj = Object.new
|
|
90
|
-
def obj.to_json
|
|
91
|
-
'{"object":"shrimp"}'
|
|
92
|
-
end
|
|
93
|
-
obj.freeze
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
it "converts the object to truncated JSON" do
|
|
97
|
-
expect(subject.length).to eq(max_len)
|
|
98
|
-
expect(subject).to be_frozen
|
|
99
|
-
|
|
100
|
-
expect(subject).to eq('{"o[Truncated]')
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
context "given an arbitrary object that doesn't respond to #to_json" do
|
|
105
|
-
let(:object) do
|
|
106
|
-
obj = Object.new
|
|
107
|
-
allow(obj).to receive(:to_json)
|
|
108
|
-
.and_raise(Airbrake::Notice::JSON_EXCEPTIONS.first)
|
|
109
|
-
obj
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
it "converts the object to a truncated string" do
|
|
113
|
-
expect(subject.length).to eq(max_len)
|
|
114
|
-
expect(subject).to eq('#<O[Truncated]')
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
shared_examples 'self returning objects' do |object|
|
|
119
|
-
it "returns the passed object" do
|
|
120
|
-
expect(described_class.new(max_size).truncate(object)).to eql(object)
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
[1, true, false, :symbol, nil].each do |object|
|
|
125
|
-
include_examples 'self returning objects', object
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
context "given a recursive array" do
|
|
129
|
-
let(:object) do
|
|
130
|
-
a = %w[aaaaa bb]
|
|
131
|
-
a << a
|
|
132
|
-
a << 'c'
|
|
133
|
-
a
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
it "prevents recursion" do
|
|
137
|
-
expect(subject).to eq(['aaa[Truncated]', 'bb', '[Circular]'])
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
context "given a recursive array with recursive hashes" do
|
|
142
|
-
let(:object) do
|
|
143
|
-
a = []
|
|
144
|
-
a << a
|
|
145
|
-
|
|
146
|
-
h = {}
|
|
147
|
-
h[:k] = h
|
|
148
|
-
a << h << 'aaaa'
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it "prevents recursion" do
|
|
152
|
-
expect(subject).to eq(['[Circular]', { k: '[Circular]' }, 'aaa[Truncated]'])
|
|
153
|
-
expect(subject).to be_frozen
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
context "given a recursive set with recursive arrays" do
|
|
158
|
-
let(:object) do
|
|
159
|
-
s = Set.new
|
|
160
|
-
s << s
|
|
161
|
-
|
|
162
|
-
h = {}
|
|
163
|
-
h[:k] = h
|
|
164
|
-
s << h << 'aaaa'
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
it "prevents recursion" do
|
|
168
|
-
expect(subject).to eq(
|
|
169
|
-
Set.new(['[Circular]', { k: '[Circular]' }, 'aaa[Truncated]'])
|
|
170
|
-
)
|
|
171
|
-
expect(subject).to be_frozen
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
context "given a hash with long strings" do
|
|
176
|
-
let(:object) do
|
|
177
|
-
{
|
|
178
|
-
a: multiply_by_2_max_len('a'),
|
|
179
|
-
b: multiply_by_2_max_len('b'),
|
|
180
|
-
c: { d: multiply_by_2_max_len('d'), e: 'e' }
|
|
181
|
-
}
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
it "truncates the long strings" do
|
|
185
|
-
expect(subject).to eq(
|
|
186
|
-
a: 'aaa[Truncated]', b: 'bbb[Truncated]', c: { d: 'ddd[Truncated]', e: 'e' }
|
|
187
|
-
)
|
|
188
|
-
expect(subject).to be_frozen
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
context "given a string with valid unicode characters" do
|
|
193
|
-
let(:object) { "€€€€€" }
|
|
194
|
-
|
|
195
|
-
it "truncates the string" do
|
|
196
|
-
expect(subject).to eq("€€€[Truncated]")
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
context "given an ASCII-8BIT string with invalid characters" do
|
|
201
|
-
let(:object) do
|
|
202
|
-
# Shenanigans to get a bad ASCII-8BIT string. Direct conversion raises error.
|
|
203
|
-
encoded = Base64.encode64("\xD3\xE6\xBC\x9D\xBA").encode!('ASCII-8BIT')
|
|
204
|
-
Base64.decode64(encoded).freeze
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
it "converts and truncates the string to UTF-8" do
|
|
208
|
-
expect(subject).to eq("���[Truncated]")
|
|
209
|
-
expect(subject).to be_frozen
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
context "given an array with hashes and hash-like objects with identical keys" do
|
|
214
|
-
let(:hashie) { Class.new(Hash) }
|
|
215
|
-
|
|
216
|
-
let(:object) do
|
|
217
|
-
{
|
|
218
|
-
errors: [
|
|
219
|
-
{ file: 'a' },
|
|
220
|
-
{ file: 'a' },
|
|
221
|
-
hashie.new.merge(file: 'bcde')
|
|
222
|
-
]
|
|
223
|
-
}
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
it "truncates values" do
|
|
227
|
-
expect(subject).to eq(
|
|
228
|
-
errors: [
|
|
229
|
-
{ file: 'a' },
|
|
230
|
-
{ file: 'a' },
|
|
231
|
-
hashie.new.merge(file: 'bcd[Truncated]')
|
|
232
|
-
]
|
|
233
|
-
)
|
|
234
|
-
expect(subject).to be_frozen
|
|
235
|
-
end
|
|
236
|
-
end
|
|
237
|
-
end
|
|
238
|
-
end
|