Commit 7352a1ce773b04a326c841531fe4b6b338a2cac6

Authored by Stephen Crosby
1 parent f13bc748
Exists in master and in 1 other branch production

add specs for refingerprint/recache classes

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
1 1 Fabricator :notice do
  2 + app
2 3 err
3 4 error_class 'FooError'
4 5 message 'Too Much Bar'
... ...
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
... ...
spec/interactors/problem_recacher_spec.rb 0 → 100644
... ... @@ -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
... ...