From 195271728af14e58e3b873c68b3b492e11fe9908 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Fri, 9 Sep 2016 11:29:37 +0300 Subject: [PATCH] filter_chain: don't try to filter nil files Fixes #117 (undefined method `sub!' for nil:NilClass) The problem can be reproduced when airbrake-ruby tries to send an exception with a backtrace, which couldn't be parsed. In that case we put the whole frame into `function`, leaving `line` and `file` nil. --- CHANGELOG.md | 2 ++ lib/airbrake-ruby/filter_chain.rb | 8 +++++-- spec/filter_chain_spec.rb | 36 +++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4289197b..487883f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ Airbrake Ruby Changelog * Started validating the 'environment' config option (a warning will be printed, if it is misconfigured) ([#115](https://github.com/airbrake/airbrake-ruby/pull/115)) +* Fixed error while filtering unparseable backtraces + ([#120](https://github.com/airbrake/airbrake-ruby/pull/120)) ### [v1.4.6][v1.4.6] (August 18, 2016) diff --git a/lib/airbrake-ruby/filter_chain.rb b/lib/airbrake-ruby/filter_chain.rb index 33e9f946..7bc7376a 100644 --- a/lib/airbrake-ruby/filter_chain.rb +++ b/lib/airbrake-ruby/filter_chain.rb @@ -13,7 +13,10 @@ class FilterChain notice[:errors].each do |error| Gem.path.each do |gem_path| error[:backtrace].each do |frame| - frame[:file].sub!(/\A#{gem_path}/, '[GEM_ROOT]'.freeze) + # If the frame is unparseable, then 'file' is nil, thus nothing to + # filter (all frame's data is in 'function' instead). + next unless (file = frame[:file]) + file.sub!(/\A#{gem_path}/, '[GEM_ROOT]'.freeze) end end end @@ -67,7 +70,8 @@ def root_directory_filter(root_directory) proc do |notice| notice[:errors].each do |error| error[:backtrace].each do |frame| - frame[:file].sub!(/\A#{root_directory}/, '[PROJECT_ROOT]'.freeze) + next unless (file = frame[:file]) + file.sub!(/\A#{root_directory}/, '[PROJECT_ROOT]'.freeze) end end end diff --git a/spec/filter_chain_spec.rb b/spec/filter_chain_spec.rb index 9e2490a6..34a40d42 100644 --- a/spec/filter_chain_spec.rb +++ b/spec/filter_chain_spec.rb @@ -152,6 +152,42 @@ to(change { notice.ignored? }.from(false).to(true)) end end + + context "gem root filter" do + let(:ex) do + AirbrakeTestError.new.tap do |error| + error.set_backtrace(['(unparseable/frame.rb:23)']) + end + end + + it "does not filter file if it is nil" do + config.logger = Logger.new('/dev/null') + notice = Airbrake::Notice.new(config, ex) + + expect(notice[:errors].first[:file]).to be_nil + expect { @chain.refine(notice) }. + not_to change { notice[:errors].first[:file] } + end + end + + context "root directory filter" do + let(:ex) do + AirbrakeTestError.new.tap do |error| + error.set_backtrace(['(unparseable/frame.rb:23)']) + end + end + + it "does not filter file if it is nil" do + config.logger = Logger.new('/dev/null') + config.root_directory = '/bingo/bango' + notice = Airbrake::Notice.new(config, ex) + filter_chain = described_class.new(config) + + expect(notice[:errors].first[:file]).to be_nil + expect { filter_chain.refine(notice) }. + not_to change { notice[:errors].first[:file] } + end + end end end end