Commit 7352a1ce773b04a326c841531fe4b6b338a2cac6
1 parent
f13bc748
Exists in
master
and in
1 other branch
add specs for refingerprint/recache classes
Showing
8 changed files
with
98 additions
and
34 deletions
Show diff stats
app/interactors/notice_refingerprinter.rb
... | ... | @@ -15,19 +15,21 @@ class NoticeRefingerprinter |
15 | 15 | end |
16 | 16 | |
17 | 17 | puts 'Finished generating notice fingerprints' |
18 | - end | |
18 | + puts 'Destroying orphaned err records' | |
19 | + | |
20 | + Err.each { |e| e.destroy if e.notices.size == 0 } | |
19 | 21 | |
20 | - def self.apps | |
21 | - @apps ||= App.all.index_by(&:id) | |
22 | + puts 'Finished destroying orphaned err records' | |
22 | 23 | end |
23 | 24 | |
24 | 25 | def self.refingerprint(notice) |
25 | - app = apps[notice.try(:err).try(:problem).try(:app_id)] | |
26 | - app.find_or_create_err!( | |
26 | + app = notice.app | |
27 | + notice.err = app.find_or_create_err!( | |
27 | 28 | error_class: notice.error_class, |
28 | 29 | environment: notice.environment_name, |
29 | 30 | fingerprint: app.notice_fingerprinter.generate(app.api_key, notice, notice.backtrace) |
30 | 31 | ) |
32 | + notice.save! | |
31 | 33 | end |
32 | 34 | |
33 | 35 | def self.puts(*args) | ... | ... |
app/models/app.rb
... | ... | @@ -65,16 +65,15 @@ class App |
65 | 65 | # * <tt>:fingerprint</tt> - a unique value identifying the notice |
66 | 66 | # |
67 | 67 | def find_or_create_err!(attrs) |
68 | - Err.where( | |
69 | - :fingerprint => attrs[:fingerprint] | |
70 | - ).first || ( | |
71 | - problem = problems.create!( | |
72 | - error_class: attrs[:error_class], | |
73 | - environment: attrs[:environment], | |
74 | - app_name: name | |
75 | - ) | |
76 | - problem.errs.create!(attrs.slice(:fingerprint, :problem_id)) | |
68 | + err = Err.where(fingerprint: attrs[:fingerprint]).first | |
69 | + return err if err | |
70 | + | |
71 | + problem = problems.create!( | |
72 | + error_class: attrs[:error_class], | |
73 | + environment: attrs[:environment], | |
74 | + app_name: name | |
77 | 75 | ) |
76 | + problem.errs.create!(attrs.slice(:fingerprint, :problem_id)) | |
78 | 77 | end |
79 | 78 | |
80 | 79 | # Mongoid Bug: find(id) on association proxies returns an Enumerator | ... | ... |
app/models/notice.rb
... | ... | @@ -29,9 +29,7 @@ class Notice |
29 | 29 | scope :ordered, ->{ order_by(:created_at.asc) } |
30 | 30 | scope :reverse_ordered, ->{ order_by(:created_at.desc) } |
31 | 31 | scope :for_errs, Proc.new { |errs| |
32 | - if (ids = errs.all.map(&:id)) && ids.present? | |
33 | - where(:err_id.in => ids) | |
34 | - end | |
32 | + where(:err_id.in => errs.all.map(&:id)) | |
35 | 33 | } |
36 | 34 | |
37 | 35 | def user_agent | ... | ... |
app/models/notice_fingerprinter.rb
... | ... | @@ -14,7 +14,7 @@ class NoticeFingerprinter |
14 | 14 | embedded_in :site_config |
15 | 15 | |
16 | 16 | def generate(api_key, notice, backtrace) |
17 | - material = [] | |
17 | + material = [ api_key ] | |
18 | 18 | material << notice.error_class if error_class |
19 | 19 | material << notice.filtered_message if message |
20 | 20 | material << notice.component if component | ... | ... |
spec/fabricators/backtrace_fabricator.rb
... | ... | @@ -7,13 +7,3 @@ Fabricator :backtrace do |
7 | 7 | } |
8 | 8 | end |
9 | 9 | end |
10 | - | |
11 | -Fabricator :short_backtrace do | |
12 | - lines(:count => 5) do | |
13 | - { | |
14 | - number: rand(999), | |
15 | - file: "/path/to/file/#{SecureRandom.hex(4)}.rb", | |
16 | - method: ActiveSupport.methods.shuffle.first | |
17 | - } | |
18 | - end | |
19 | -end | ... | ... |
spec/fabricators/notice_fabricator.rb
spec/interactors/notice_refingerprinter_spec.rb
1 | 1 | describe NoticeRefingerprinter do |
2 | + let(:app) { Fabricate(:app) } | |
2 | 3 | let(:backtrace) do |
3 | 4 | Fabricate(:backtrace) |
4 | 5 | end |
5 | 6 | |
6 | - let(:notices) do | |
7 | - 5.times.map do | |
8 | - Fabricate(:notice, backtrace: backtrace) | |
7 | + before do | |
8 | + notices | |
9 | + end | |
10 | + | |
11 | + context 'identical backtraces' do | |
12 | + let(:notices) do | |
13 | + 5.times.map do | |
14 | + notice = Fabricate(:notice, backtrace: backtrace, app: app) | |
15 | + notice.save! | |
16 | + notice | |
17 | + end | |
18 | + end | |
19 | + | |
20 | + it 'has only one err' do | |
21 | + described_class.run | |
22 | + expect(Err.count).to eq(1) | |
9 | 23 | end |
10 | 24 | end |
11 | 25 | |
12 | - it 'shits' do | |
13 | - binding.pry | |
14 | - 1 | |
26 | + context 'minor backtrace differences' do | |
27 | + let(:notices) do | |
28 | + line_numbers = [1, 1, 2, 2, 3] | |
29 | + 5.times.map do | |
30 | + b = backtrace.clone | |
31 | + b.lines[5][:number] = line_numbers.shift | |
32 | + b.save! | |
33 | + notice = Fabricate(:notice, backtrace: b, app: app) | |
34 | + notice.save! | |
35 | + end | |
36 | + end | |
37 | + | |
38 | + it 'has three errs with default fingerprinter' do | |
39 | + described_class.run | |
40 | + expect(Err.count).to eq(3) | |
41 | + end | |
42 | + | |
43 | + it 'has one err when limiting backtrace line count' do | |
44 | + fingerprinter = app.notice_fingerprinter | |
45 | + fingerprinter.backtrace_lines = 4 | |
46 | + fingerprinter.save! | |
47 | + | |
48 | + described_class.run | |
49 | + expect(Err.count).to eq(1) | |
50 | + end | |
15 | 51 | end |
16 | 52 | end | ... | ... |
... | ... | @@ -0,0 +1,38 @@ |
1 | +describe ProblemRecacher do | |
2 | + let(:app) { Fabricate(:app) } | |
3 | + let(:backtrace) do | |
4 | + Fabricate(:backtrace) | |
5 | + end | |
6 | + | |
7 | + before do | |
8 | + notices | |
9 | + | |
10 | + NoticeRefingerprinter.run | |
11 | + described_class.run | |
12 | + end | |
13 | + | |
14 | + context 'minor backtrace differences' do | |
15 | + let(:notices) do | |
16 | + line_numbers = [1, 1, 2, 2, 3] | |
17 | + 5.times.map do | |
18 | + b = backtrace.clone | |
19 | + b.lines[5][:number] = line_numbers.shift | |
20 | + b.save! | |
21 | + notice = Fabricate(:notice, backtrace: b, app: app) | |
22 | + notice.save! | |
23 | + notice | |
24 | + end | |
25 | + end | |
26 | + | |
27 | + it 'has three problems for the five notices' do | |
28 | + expect(Notice.count).to eq(5) | |
29 | + expect(Problem.count).to eq(3) | |
30 | + end | |
31 | + | |
32 | + it 'the problems have the right cached attributes' do | |
33 | + problem = notices.first.reload.problem | |
34 | + | |
35 | + expect(problem.notices_count).to eq(2) | |
36 | + end | |
37 | + end | |
38 | +end | ... | ... |