diff --git a/app/models/fingerprint.rb b/app/models/fingerprint.rb index 0dd435c..f76a1b8 100644 --- a/app/models/fingerprint.rb +++ b/app/models/fingerprint.rb @@ -1,33 +1,23 @@ require 'digest/sha1' class Fingerprint + attr_reader :notice, :api_key - + def self.generate(notice, api_key) self.new(notice, api_key).to_s end - + def initialize(notice, api_key) @notice = notice @api_key = api_key end - - - + def to_s Digest::SHA1.hexdigest(fingerprint_source.to_s) end - - def fingerprint_source - # Find the first backtrace line with a file and line number. - if line = notice.backtrace.lines.detect {|l| l.number.present? && l.file.present? } - # If line exists, only use file and number. - file_or_message = "#{line.file}:#{line.number}" - else - # If no backtrace, use error message - file_or_message = notice.message - end + def fingerprint_source { :file_or_message => file_or_message, :error_class => notice.error_class, @@ -37,5 +27,9 @@ class Fingerprint :api_key => api_key } end - + + def file_or_message + @file_or_message ||= notice.message + notice.backtrace.fingerprint + end + end diff --git a/spec/models/fingerprint_spec.rb b/spec/models/fingerprint_spec.rb index 9b6f93c..1c47f3e 100644 --- a/spec/models/fingerprint_spec.rb +++ b/spec/models/fingerprint_spec.rb @@ -3,19 +3,36 @@ require 'spec_helper' describe Fingerprint do context '#generate' do - before do - @backtrace = Backtrace.find_or_create(:raw => [ + let(:backtrace) { + Backtrace.create(:raw => [ {"number"=>"425", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"_run__2115867319__process_action__262109504__callbacks"}, {"number"=>"404", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"send"}, {"number"=>"404", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"_run_process_action_callbacks"} ]) + } + let(:notice1) { Fabricate.build(:notice, :backtrace => backtrace) } + let(:notice2) { Fabricate.build(:notice, :backtrace => backtrace_2) } + + context "with same backtrace" do + let(:backtrace_2) { backtrace } + it 'should create the same fingerprint for two notices' do + expect(Fingerprint.generate(notice1, "api key")).to eq Fingerprint.generate(notice2, "api key") + end end - - it 'should create the same fingerprint for two notices with the same backtrace' do - notice1 = Fabricate.build(:notice, :backtrace => @backtrace) - notice2 = Fabricate.build(:notice, :backtrace => @backtrace) - - Fingerprint.generate(notice1, "api key").should == Fingerprint.generate(notice2, "api key") + + context "with different backtrace with only last line change" do + let(:backtrace_2) { + backtrace + backtrace.lines.last.number = 401 + backtrace.send(:generate_fingerprint) + backtrace.save + backtrace + } + it 'should not same fingerprint' do + expect( + Fingerprint.generate(notice1, "api key") + ).not_to eql Fingerprint.generate(notice2, "api key") + end end end -- libgit2 0.21.2