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 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