airbrake-ruby 2.5.0.rc.2 → 2.5.0.rc.3
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/backtrace.rb +34 -21
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/backtrace_spec.rb +89 -20
- data/spec/code_hunk_spec.rb +10 -10
- data/spec/fixtures/notroot.txt +7 -0
- data/spec/fixtures/{code.rb → project_root/code.rb} +0 -0
- data/spec/fixtures/{empty_file.rb → project_root/empty_file.rb} +0 -0
- data/spec/fixtures/{long_line.txt → project_root/long_line.txt} +0 -0
- data/spec/fixtures/{short_file.rb → project_root/short_file.rb} +0 -0
- data/spec/helpers.rb +4 -0
- metadata +12 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 313672bde1f31342c0fce790b1f6285c9b125b4e
|
4
|
+
data.tar.gz: 505361aa89c2f456b91ae53c76a73b61cb180838
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65b85420d818a1ab8a4149ca642710c316626d7b283a24a2bb78712f8aa731dfd5946f88da6ab674d69037c50390b726fcc183007156189b3d9bb26c3143b2fb
|
7
|
+
data.tar.gz: 8fcbf41b9f55a93ec262525d39d282f08a8dd2b73a4d96f87e084b440d349b8cf4347e3a48181419906af93ee2bda6b3ff34997af5aa62f8065aed4e90777da9
|
@@ -96,6 +96,10 @@ module Airbrake
|
|
96
96
|
EXECJS_SIMPLIFIED = /\A.+ \(.+:\d+:\d+\)\z/
|
97
97
|
end
|
98
98
|
|
99
|
+
##
|
100
|
+
# @return [Integer] how many first frames should include code hunks
|
101
|
+
CODE_FRAME_LIMIT = 10
|
102
|
+
|
99
103
|
##
|
100
104
|
# Parses an exception's backtrace.
|
101
105
|
#
|
@@ -104,22 +108,7 @@ module Airbrake
|
|
104
108
|
# @return [Array<Hash{Symbol=>String,Integer}>] the parsed backtrace
|
105
109
|
def self.parse(config, exception)
|
106
110
|
return [] if exception.backtrace.nil? || exception.backtrace.none?
|
107
|
-
|
108
|
-
regexp = best_regexp_for(exception)
|
109
|
-
|
110
|
-
exception.backtrace.map do |stackframe|
|
111
|
-
frame = match_frame(regexp, stackframe)
|
112
|
-
|
113
|
-
unless frame
|
114
|
-
config.logger.error(
|
115
|
-
"can't parse '#{stackframe}' (please file an issue so we can fix " \
|
116
|
-
"it: https://github.com/airbrake/airbrake-ruby/issues/new)"
|
117
|
-
)
|
118
|
-
frame = { file: nil, line: nil, function: stackframe }
|
119
|
-
end
|
120
|
-
|
121
|
-
stack_frame(config, frame)
|
122
|
-
end
|
111
|
+
parse_backtrace(config, exception)
|
123
112
|
end
|
124
113
|
|
125
114
|
##
|
@@ -176,15 +165,12 @@ module Airbrake
|
|
176
165
|
end
|
177
166
|
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
178
167
|
|
179
|
-
def stack_frame(
|
180
|
-
|
168
|
+
def stack_frame(match)
|
169
|
+
{
|
181
170
|
file: match[:file],
|
182
171
|
line: (Integer(match[:line]) if match[:line]),
|
183
172
|
function: match[:function]
|
184
173
|
}
|
185
|
-
|
186
|
-
populate_code(config, frame) if config.code_hunks
|
187
|
-
frame
|
188
174
|
end
|
189
175
|
|
190
176
|
def match_frame(regexp, stackframe)
|
@@ -194,6 +180,33 @@ module Airbrake
|
|
194
180
|
Patterns::GENERIC.match(stackframe)
|
195
181
|
end
|
196
182
|
|
183
|
+
def parse_backtrace(config, exception)
|
184
|
+
regexp = best_regexp_for(exception)
|
185
|
+
|
186
|
+
exception.backtrace.map.with_index do |stackframe, i|
|
187
|
+
unless (match = match_frame(regexp, stackframe))
|
188
|
+
config.logger.error(
|
189
|
+
"can't parse '#{stackframe}' (please file an issue so we can fix " \
|
190
|
+
"it: https://github.com/airbrake/airbrake-ruby/issues/new)"
|
191
|
+
)
|
192
|
+
match = { file: nil, line: nil, function: stackframe }
|
193
|
+
end
|
194
|
+
|
195
|
+
frame = stack_frame(match)
|
196
|
+
next(frame) unless config.code_hunks
|
197
|
+
|
198
|
+
if config.root_directory
|
199
|
+
if frame[:file].start_with?(config.root_directory)
|
200
|
+
populate_code(config, frame)
|
201
|
+
end
|
202
|
+
elsif i < CODE_FRAME_LIMIT
|
203
|
+
populate_code(config, frame)
|
204
|
+
end
|
205
|
+
|
206
|
+
frame
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
197
210
|
def populate_code(config, frame)
|
198
211
|
code = Airbrake::CodeHunk.new(config).get(frame[:file], frame[:line])
|
199
212
|
frame[:code] = code if code
|
data/spec/backtrace_spec.rb
CHANGED
@@ -297,29 +297,98 @@ RSpec.describe Airbrake::Backtrace do
|
|
297
297
|
config
|
298
298
|
end
|
299
299
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
300
|
+
context "and when root_directory is configured" do
|
301
|
+
before { config.root_directory = project_root_path('') }
|
302
|
+
|
303
|
+
let(:parsed_backtrace) do
|
304
|
+
[
|
305
|
+
{
|
306
|
+
file: project_root_path('code.rb'),
|
307
|
+
line: 94,
|
308
|
+
function: 'to_json',
|
309
|
+
code: {
|
310
|
+
92 => ' loop do',
|
311
|
+
93 => ' begin',
|
312
|
+
94 => ' json = @payload.to_json',
|
313
|
+
95 => ' rescue *JSON_EXCEPTIONS => ex',
|
314
|
+
# rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
|
315
|
+
96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
|
316
|
+
# rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
|
317
|
+
}
|
318
|
+
},
|
319
|
+
{
|
320
|
+
file: fixture_path('notroot.txt'),
|
321
|
+
line: 3,
|
322
|
+
function: 'pineapple'
|
314
323
|
}
|
315
|
-
|
316
|
-
|
324
|
+
]
|
325
|
+
end
|
326
|
+
|
327
|
+
it "attaches code to those frames files of which match root_directory" do
|
328
|
+
ex = RuntimeError.new
|
329
|
+
backtrace = [
|
330
|
+
project_root_path('code.rb') + ":94:in `to_json'",
|
331
|
+
fixture_path('notroot.txt' + ":3:in `pineapple'")
|
332
|
+
]
|
333
|
+
ex.set_backtrace(backtrace)
|
334
|
+
expect(described_class.parse(config, ex)).to eq(parsed_backtrace)
|
335
|
+
end
|
317
336
|
end
|
318
337
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
338
|
+
context "and when root_directory isn't configured" do
|
339
|
+
before do
|
340
|
+
config.root_directory = nil
|
341
|
+
stub_const('Airbrake::Backtrace::CODE_FRAME_LIMIT', 2)
|
342
|
+
end
|
343
|
+
|
344
|
+
let(:parsed_backtrace) do
|
345
|
+
[
|
346
|
+
{
|
347
|
+
file: project_root_path('code.rb'),
|
348
|
+
line: 94,
|
349
|
+
function: 'to_json',
|
350
|
+
code: {
|
351
|
+
92 => ' loop do',
|
352
|
+
93 => ' begin',
|
353
|
+
94 => ' json = @payload.to_json',
|
354
|
+
95 => ' rescue *JSON_EXCEPTIONS => ex',
|
355
|
+
# rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
|
356
|
+
96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
|
357
|
+
# rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
|
358
|
+
}
|
359
|
+
},
|
360
|
+
{
|
361
|
+
file: project_root_path('code.rb'),
|
362
|
+
line: 95,
|
363
|
+
function: 'to_json',
|
364
|
+
code: {
|
365
|
+
93 => ' begin',
|
366
|
+
94 => ' json = @payload.to_json',
|
367
|
+
95 => ' rescue *JSON_EXCEPTIONS => ex',
|
368
|
+
# rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
|
369
|
+
96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
|
370
|
+
# rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
|
371
|
+
97 => ' else'
|
372
|
+
}
|
373
|
+
},
|
374
|
+
{
|
375
|
+
file: project_root_path('code.rb'),
|
376
|
+
line: 96,
|
377
|
+
function: 'to_json'
|
378
|
+
}
|
379
|
+
]
|
380
|
+
end
|
381
|
+
|
382
|
+
it "attaches code to first N frames" do
|
383
|
+
ex = RuntimeError.new
|
384
|
+
backtrace = [
|
385
|
+
project_root_path('code.rb') + ":94:in `to_json'",
|
386
|
+
project_root_path('code.rb') + ":95:in `to_json'",
|
387
|
+
project_root_path('code.rb') + ":96:in `to_json'"
|
388
|
+
]
|
389
|
+
ex.set_backtrace(backtrace)
|
390
|
+
expect(described_class.parse(config, ex)).to eq(parsed_backtrace)
|
391
|
+
end
|
323
392
|
end
|
324
393
|
end
|
325
394
|
end
|
data/spec/code_hunk_spec.rb
CHANGED
@@ -5,33 +5,33 @@ RSpec.describe Airbrake::CodeHunk do
|
|
5
5
|
|
6
6
|
after do
|
7
7
|
%w[empty_file.rb code.rb banana.rb short_file.rb long_line.txt].each do |f|
|
8
|
-
Airbrake::FileCache[
|
8
|
+
Airbrake::FileCache[project_root_path(f)] = nil
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
describe "#to_h" do
|
13
13
|
context "when file is empty" do
|
14
14
|
subject do
|
15
|
-
described_class.new(config).get(
|
15
|
+
described_class.new(config).get(project_root_path('empty_file.rb'), 1)
|
16
16
|
end
|
17
17
|
|
18
18
|
it { is_expected.to eq(1 => '') }
|
19
19
|
end
|
20
20
|
|
21
21
|
context "when line is nil" do
|
22
|
-
subject { described_class.new(config).get(
|
22
|
+
subject { described_class.new(config).get(project_root_path('code.rb'), nil) }
|
23
23
|
|
24
24
|
it { is_expected.to be_nil }
|
25
25
|
end
|
26
26
|
|
27
27
|
context "when a file doesn't exist" do
|
28
|
-
subject { described_class.new(config).get(
|
28
|
+
subject { described_class.new(config).get(project_root_path('banana.rb'), 1) }
|
29
29
|
|
30
30
|
it { is_expected.to be_nil }
|
31
31
|
end
|
32
32
|
|
33
33
|
context "when a file has less than NLINES lines before start line" do
|
34
|
-
subject { described_class.new(config).get(
|
34
|
+
subject { described_class.new(config).get(project_root_path('code.rb'), 1) }
|
35
35
|
|
36
36
|
it do
|
37
37
|
is_expected.to(
|
@@ -47,7 +47,7 @@ RSpec.describe Airbrake::CodeHunk do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
context "when a file has less than NLINES lines after end line" do
|
50
|
-
subject { described_class.new(config).get(
|
50
|
+
subject { described_class.new(config).get(project_root_path('code.rb'), 222) }
|
51
51
|
|
52
52
|
it do
|
53
53
|
is_expected.to(
|
@@ -61,7 +61,7 @@ RSpec.describe Airbrake::CodeHunk do
|
|
61
61
|
|
62
62
|
context "when a file has less than NLINES lines before and after" do
|
63
63
|
subject do
|
64
|
-
described_class.new(config).get(
|
64
|
+
described_class.new(config).get(project_root_path('short_file.rb'), 2)
|
65
65
|
end
|
66
66
|
|
67
67
|
it do
|
@@ -76,7 +76,7 @@ RSpec.describe Airbrake::CodeHunk do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
context "when a file has enough lines before and after" do
|
79
|
-
subject { described_class.new(config).get(
|
79
|
+
subject { described_class.new(config).get(project_root_path('code.rb'), 100) }
|
80
80
|
|
81
81
|
it do
|
82
82
|
is_expected.to(
|
@@ -93,7 +93,7 @@ RSpec.describe Airbrake::CodeHunk do
|
|
93
93
|
|
94
94
|
context "when a line exceeds the length limit" do
|
95
95
|
subject do
|
96
|
-
described_class.new(config).get(
|
96
|
+
described_class.new(config).get(project_root_path('long_line.txt'), 1)
|
97
97
|
end
|
98
98
|
|
99
99
|
it "strips the line" do
|
@@ -110,7 +110,7 @@ RSpec.describe Airbrake::CodeHunk do
|
|
110
110
|
out = StringIO.new
|
111
111
|
config = Airbrake::Config.new
|
112
112
|
config.logger = Logger.new(out)
|
113
|
-
expect(described_class.new(config).get(
|
113
|
+
expect(described_class.new(config).get(project_root_path('code.rb'), 1)).to(
|
114
114
|
eq(1 => '')
|
115
115
|
)
|
116
116
|
expect(out.string).to match(/can't read code hunk.+Permission denied/)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/helpers.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: airbrake-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.5.0.rc.
|
4
|
+
version: 2.5.0.rc.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Airbrake Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-10-
|
11
|
+
date: 2017-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -80,20 +80,6 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '2'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rubocop
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0.50'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0.50'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: public_suffix
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -166,10 +152,11 @@ files:
|
|
166
152
|
- spec/filters/root_directory_filter_spec.rb
|
167
153
|
- spec/filters/system_exit_filter_spec.rb
|
168
154
|
- spec/filters/thread_filter_spec.rb
|
169
|
-
- spec/fixtures/
|
170
|
-
- spec/fixtures/
|
171
|
-
- spec/fixtures/
|
172
|
-
- spec/fixtures/
|
155
|
+
- spec/fixtures/notroot.txt
|
156
|
+
- spec/fixtures/project_root/code.rb
|
157
|
+
- spec/fixtures/project_root/empty_file.rb
|
158
|
+
- spec/fixtures/project_root/long_line.txt
|
159
|
+
- spec/fixtures/project_root/short_file.rb
|
173
160
|
- spec/helpers.rb
|
174
161
|
- spec/nested_exception_spec.rb
|
175
162
|
- spec/notice_spec.rb
|
@@ -218,10 +205,11 @@ test_files:
|
|
218
205
|
- spec/filters/root_directory_filter_spec.rb
|
219
206
|
- spec/filters/system_exit_filter_spec.rb
|
220
207
|
- spec/filters/thread_filter_spec.rb
|
221
|
-
- spec/fixtures/
|
222
|
-
- spec/fixtures/
|
223
|
-
- spec/fixtures/
|
224
|
-
- spec/fixtures/
|
208
|
+
- spec/fixtures/notroot.txt
|
209
|
+
- spec/fixtures/project_root/code.rb
|
210
|
+
- spec/fixtures/project_root/empty_file.rb
|
211
|
+
- spec/fixtures/project_root/long_line.txt
|
212
|
+
- spec/fixtures/project_root/short_file.rb
|
225
213
|
- spec/helpers.rb
|
226
214
|
- spec/nested_exception_spec.rb
|
227
215
|
- spec/notice_spec.rb
|