aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2008-11-22 18:06:08 +0100
committerDavid Heinemeier Hansson <david@loudthinking.com>2008-11-22 18:06:08 +0100
commitf42c77f927eb49b00e84d355e07de48723d03fcb (patch)
tree2a459814a9708f292c99e9c5e99dd41d2d801353 /activesupport
parenta026b4c983681b71d876ea37958c3e5bc605acac (diff)
downloadrails-f42c77f927eb49b00e84d355e07de48723d03fcb.tar.gz
rails-f42c77f927eb49b00e84d355e07de48723d03fcb.tar.bz2
rails-f42c77f927eb49b00e84d355e07de48723d03fcb.zip
Added ActiveSupport::BacktraceCleaner and Rails::BacktraceCleaner for cutting down on backtrace noise (inspired by the Thoughtbot Quiet Backtrace plugin) [DHH]
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/lib/active_support.rb1
-rw-r--r--activesupport/lib/active_support/backtrace_cleaner.rb72
-rw-r--r--activesupport/lib/active_support/core_ext/exception.rb1
-rw-r--r--activesupport/lib/active_support/test_case.rb10
-rw-r--r--activesupport/test/abstract_unit.rb1
-rw-r--r--activesupport/test/clean_backtrace_test.rb47
-rw-r--r--activesupport/test/core_ext/array_ext_test.rb2
8 files changed, 133 insertions, 3 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index d0895bb709..5e1b1cb4b0 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*2.3.0 [Edge]*
+* Added ActiveSupport::BacktraceCleaner to cut down on backtrace noise according to filters and silencers [DHH]
+
* Added Object#try. ( Taken from http://ozmm.org/posts/try.html ) [Chris Wanstrath]
* Added Enumerable#none? to check that none of the elements match the block #1408 [Damian Janowski]
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index d2a7df8bf0..cbfd95f092 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -29,6 +29,7 @@ require 'active_support/callbacks'
require 'active_support/core_ext'
require 'active_support/buffered_logger'
+require 'active_support/backtrace_cleaner'
require 'active_support/gzip'
require 'active_support/cache'
diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb
new file mode 100644
index 0000000000..0e262c003e
--- /dev/null
+++ b/activesupport/lib/active_support/backtrace_cleaner.rb
@@ -0,0 +1,72 @@
+module ActiveSupport
+ # Many backtraces include too much information that's not relevant for the context. This makes it hard to find the signal
+ # in the backtrace and adds debugging time. With a BacktraceCleaner, you can setup filters and silencers for your particular
+ # context, so only the relevant lines are included.
+ #
+ # If you need to reconfigure an existing BacktraceCleaner, like the one in Rails, to show as much as possible, you can always
+ # call BacktraceCleaner#remove_silencers!
+ #
+ # Example:
+ #
+ # bc = BacktraceCleaner.new
+ # bc.add_filter { |line| line.gsub(Rails.root, '') }
+ # bc.add_silencer { |line| line =~ /mongrel|rubygems/ }
+ # bc.clean(exception.backtrace) # will strip the Rails.root prefix and skip any lines from mongrel or rubygems
+ #
+ # Inspired by the Quiet Backtrace gem by Thoughtbot.
+ class BacktraceCleaner
+ def initialize
+ @filters, @silencers = [], []
+ end
+
+ # Returns the backtrace after all filters and silencers has been run against it. Filters run first, then silencers.
+ def clean(backtrace)
+ silence(filter(backtrace))
+ end
+
+ # Adds a filter from the block provided. Each line in the backtrace will be mapped against this filter.
+ #
+ # Example:
+ #
+ # # Will turn "/my/rails/root/app/models/person.rb" into "/app/models/person.rb"
+ # backtrace_cleaner.add_filter { |line| line.gsub(Rails.root, '') }
+ def add_filter(&block)
+ @filters << block
+ end
+
+ # Adds a silencer from the block provided. If the silencer returns true for a given line, it'll be excluded from the
+ # clean backtrace.
+ #
+ # Example:
+ #
+ # # Will reject all lines that include the word "mongrel", like "/gems/mongrel/server.rb" or "/app/my_mongrel_server/rb"
+ # backtrace_cleaner.add_silencer { |line| line =~ /mongrel/ }
+ def add_silencer(&block)
+ @silencers << block
+ end
+
+ # Will remove all silencers, but leave in the filters. This is useful if your context of debugging suddenly expands as
+ # you suspect a bug in the libraries you use.
+ def remove_silencers!
+ @silencers = []
+ end
+
+
+ private
+ def filter(backtrace)
+ @filters.each do |f|
+ backtrace = backtrace.map { |line| f.call(line) }
+ end
+
+ backtrace
+ end
+
+ def silence(backtrace)
+ @silencers.each do |s|
+ backtrace = backtrace.reject { |line| s.call(line) }
+ end
+
+ backtrace
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/exception.rb b/activesupport/lib/active_support/core_ext/exception.rb
index 57c8568334..73470cbe05 100644
--- a/activesupport/lib/active_support/core_ext/exception.rb
+++ b/activesupport/lib/active_support/core_ext/exception.rb
@@ -6,6 +6,7 @@ module ActiveSupport
end
end
+# TODO: Turn all this into using the BacktraceCleaner.
class Exception # :nodoc:
def clean_message
Pathname.clean_within message
diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb
index 5b825b212d..d1e657c15f 100644
--- a/activesupport/lib/active_support/test_case.rb
+++ b/activesupport/lib/active_support/test_case.rb
@@ -21,15 +21,21 @@ module ActiveSupport
Assertion = MiniTest::Assertion
end
+ # TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit
# Test::Unit compatibility.
rescue LoadError
require 'test/unit/testcase'
require 'active_support/testing/default'
+ if defined?(Rails)
+ require 'rails/backtrace_cleaner'
+ Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit }
+ end
+
class TestCase < ::Test::Unit::TestCase
Assertion = Test::Unit::AssertionFailedError
include ActiveSupport::Testing::Default
- end
+ end
end
class TestCase
@@ -37,4 +43,4 @@ module ActiveSupport
include ActiveSupport::Testing::Assertions
extend ActiveSupport::Testing::Declarative
end
-end
+end \ No newline at end of file
diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb
index deb512eeb6..047f0effad 100644
--- a/activesupport/test/abstract_unit.rb
+++ b/activesupport/test/abstract_unit.rb
@@ -3,6 +3,7 @@ require 'test/unit'
gem 'mocha', '>= 0.9.0'
require 'mocha'
+$:.unshift "#{File.dirname(__FILE__)}/../lib"
require 'active_support'
require 'active_support/test_case'
diff --git a/activesupport/test/clean_backtrace_test.rb b/activesupport/test/clean_backtrace_test.rb
new file mode 100644
index 0000000000..ddbc258df1
--- /dev/null
+++ b/activesupport/test/clean_backtrace_test.rb
@@ -0,0 +1,47 @@
+require 'abstract_unit'
+
+class BacktraceCleanerFilterTest < ActiveSupport::TestCase
+ def setup
+ @bc = ActiveSupport::BacktraceCleaner.new
+ @bc.add_filter { |line| line.gsub("/my/prefix", '') }
+ end
+
+ test "backtrace should not contain prefix when it has been filtered out" do
+ assert_equal "/my/class.rb", @bc.clean([ "/my/prefix/my/class.rb" ]).first
+ end
+
+ test "backtrace should contain unaltered lines if they dont match a filter" do
+ assert_equal "/my/other_prefix/my/class.rb", @bc.clean([ "/my/other_prefix/my/class.rb" ]).first
+ end
+
+ test "backtrace should filter all lines in a backtrace" do
+ assert_equal \
+ ["/my/class.rb", "/my/module.rb"],
+ @bc.clean([ "/my/prefix/my/class.rb", "/my/prefix/my/module.rb" ])
+ end
+end
+
+class BacktraceCleanerSilencerTest < ActiveSupport::TestCase
+ def setup
+ @bc = ActiveSupport::BacktraceCleaner.new
+ @bc.add_silencer { |line| line =~ /mongrel/ }
+ end
+
+ test "backtrace should not contain lines that match the silencer" do
+ assert_equal \
+ [ "/other/class.rb" ],
+ @bc.clean([ "/mongrel/class.rb", "/other/class.rb", "/mongrel/stuff.rb" ])
+ end
+end
+
+class BacktraceCleanerFilterAndSilencerTest < ActiveSupport::TestCase
+ def setup
+ @bc = ActiveSupport::BacktraceCleaner.new
+ @bc.add_filter { |line| line.gsub("/mongrel", "") }
+ @bc.add_silencer { |line| line =~ /mongrel/ }
+ end
+
+ test "backtrace should not silence lines that has first had their silence hook filtered out" do
+ assert_equal [ "/class.rb" ], @bc.clean([ "/mongrel/class.rb" ])
+ end
+end \ No newline at end of file
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index 32cab2724b..d3edbc6826 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -21,7 +21,7 @@ class ArrayExtAccessTests < Test::Unit::TestCase
assert_equal array[2], array.third
assert_equal array[3], array.fourth
assert_equal array[4], array.fifth
- assert_equal array[41], array.fourty_two
+ assert_equal array[41], array.forty_two
end
end