airbrake-ruby 2.5.0.rc.2 → 2.5.0.rc.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9aff45eea602c2f6f86609e6625146b33f91aa33
4
- data.tar.gz: 51c9fb9f2f4e8d5df50832fbbfca92fda7e54239
3
+ metadata.gz: 313672bde1f31342c0fce790b1f6285c9b125b4e
4
+ data.tar.gz: 505361aa89c2f456b91ae53c76a73b61cb180838
5
5
  SHA512:
6
- metadata.gz: e7f2bf4d0415c18bb4385f612f7ca55ea2a8ee83259ee800dc058299e8f51ae1b51ec3c3467156a81547d2d1ad70d5717f1e6c01b53b6012f6a58a1cb141738c
7
- data.tar.gz: a8f8a22d199ad6326812daca779c664c53b83c65cc772e370d5cb7ae0a1fb92a65df5b8a33ad8645880571be5ca9f85f44cb030747c4c8ec2ae7e999102d53eb
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(config, match)
180
- frame = {
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
@@ -4,5 +4,5 @@
4
4
  module Airbrake
5
5
  ##
6
6
  # @return [String] the library version
7
- AIRBRAKE_RUBY_VERSION = '2.5.0.rc.2'.freeze
7
+ AIRBRAKE_RUBY_VERSION = '2.5.0.rc.3'.freeze
8
8
  end
@@ -297,29 +297,98 @@ RSpec.describe Airbrake::Backtrace do
297
297
  config
298
298
  end
299
299
 
300
- let(:parsed_backtrace) do
301
- [
302
- {
303
- file: File.join(fixture_path('code.rb')),
304
- line: 94,
305
- function: 'to_json',
306
- code: {
307
- 92 => ' loop do',
308
- 93 => ' begin',
309
- 94 => ' json = @payload.to_json',
310
- 95 => ' rescue *JSON_EXCEPTIONS => ex',
311
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
312
- 96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
313
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
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
- it "attaches code to each frame" do
320
- ex = RuntimeError.new
321
- ex.set_backtrace([File.join(fixture_path('code.rb') + ":94:in `to_json'")])
322
- expect(described_class.parse(config, ex)).to eq(parsed_backtrace)
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
@@ -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[fixture_path(f)] = nil
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(fixture_path('empty_file.rb'), 1)
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(fixture_path('code.rb'), nil) }
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(fixture_path('banana.rb'), 1) }
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(fixture_path('code.rb'), 1) }
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(fixture_path('code.rb'), 222) }
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(fixture_path('short_file.rb'), 2)
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(fixture_path('code.rb'), 100) }
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(fixture_path('long_line.txt'), 1)
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(fixture_path('code.rb'), 1)).to(
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/)
@@ -0,0 +1,7 @@
1
+ This
2
+ file
3
+ is
4
+ not
5
+ inside
6
+ root
7
+ directory
File without changes
data/spec/helpers.rb CHANGED
@@ -2,4 +2,8 @@ module Helpers
2
2
  def fixture_path(filename)
3
3
  File.expand_path(File.join('spec', 'fixtures', filename))
4
4
  end
5
+
6
+ def project_root_path(filename)
7
+ fixture_path(File.join('project_root', filename))
8
+ end
5
9
  end
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.2
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-18 00:00:00.000000000 Z
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/code.rb
170
- - spec/fixtures/empty_file.rb
171
- - spec/fixtures/long_line.txt
172
- - spec/fixtures/short_file.rb
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/code.rb
222
- - spec/fixtures/empty_file.rb
223
- - spec/fixtures/long_line.txt
224
- - spec/fixtures/short_file.rb
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