Commit 0360641897d4e4841086259ecdddb80c238b5193

Authored by Cyril Mougel
2 parents 83ade4a0 76c2bc27
Exists in master and in 1 other branch production

Merge pull request #597 from 1st8/better-fingerprints

Improve fingerprints when error messages differ only in object memory addresses
app/models/fingerprint.rb
@@ -29,7 +29,13 @@ class Fingerprint @@ -29,7 +29,13 @@ class Fingerprint
29 end 29 end
30 30
31 def file_or_message 31 def file_or_message
32 - @file_or_message ||= notice.message + notice.backtrace.fingerprint 32 + @file_or_message ||= unified_message + notice.backtrace.fingerprint
  33 + end
  34 +
  35 + # filter memory addresses out of object strings
  36 + # example: "#<Object:0x007fa2b33d9458>" becomes "#<Object>"
  37 + def unified_message
  38 + notice.message.gsub(/(#<.+?):[0-9a-f]x[0-9a-f]+(>)/, '\1\2')
33 end 39 end
34 40
35 end 41 end
spec/models/fingerprint_spec.rb
@@ -34,6 +34,53 @@ describe Fingerprint do @@ -34,6 +34,53 @@ describe Fingerprint do
34 ).not_to eql Fingerprint.generate(notice2, "api key") 34 ).not_to eql Fingerprint.generate(notice2, "api key")
35 end 35 end
36 end 36 end
  37 +
  38 + context 'with messages differing in object string memory addresses' do
  39 + let(:backtrace_2) { backtrace }
  40 +
  41 + before do
  42 + notice1.message = "NoMethodError: undefined method `foo' for #<ActiveSupport::HashWithIndifferentAccess:0x007f6bfe3287e8>"
  43 + notice2.message = "NoMethodError: undefined method `foo' for #<ActiveSupport::HashWithIndifferentAccess:0x007f6bfd9f5338>"
  44 + end
  45 +
  46 + its 'fingerprints should be equal' do
  47 + Fingerprint.generate(notice1, 'api key').should eq Fingerprint.generate(notice2, 'api key')
  48 + end
  49 + end
  50 +
  51 + context 'with different messages at same stacktrace' do
  52 + let(:backtrace_2) { backtrace }
  53 +
  54 + before do
  55 + notice1.message = "NoMethodError: undefined method `bar' for #<ActiveSupport::HashWithIndifferentAccess:0x007f6bfe3287e8>"
  56 + notice2.message = "NoMethodError: undefined method `bar' for nil:NilClass"
  57 + end
  58 +
  59 + its 'fingerprints should not be equal' do
  60 + Fingerprint.generate(notice1, 'api key').should_not eq Fingerprint.generate(notice2, 'api key')
  61 + end
  62 + end
  63 + end
  64 +
  65 + describe '#unified_message' do
  66 + subject{ Fingerprint.new(double('notice', message: message), 'api key').unified_message }
  67 +
  68 + context "full error message" do
  69 + let(:message) { "NoMethodError: undefined method `foo' for #<ActiveSupport::HashWithIndifferentAccess:0x007f6bfe3287e8>" }
  70 +
  71 + it 'removes memory address from object strings' do
  72 + should eq "NoMethodError: undefined method `foo' for #<ActiveSupport::HashWithIndifferentAccess>"
  73 + end
  74 + end
  75 +
  76 + context "multiple object strings in message" do
  77 + let(:message) { "#<ActiveSupport::HashWithIndifferentAccess:0x007f6bfe3287e8> #<Object:0x007fa2b33d9458>" }
  78 +
  79 + it 'removes memory addresses globally' do
  80 + should eq "#<ActiveSupport::HashWithIndifferentAccess> #<Object>"
  81 + end
  82 + end
  83 +
37 end 84 end
38 85
39 end 86 end