Merged updates from trunk into stable branch
[feedcatcher.git] / vendor / rails / activesupport / lib / active_support / backtrace_cleaner.rb
1 module ActiveSupport
2 # Many backtraces include too much information that's not relevant for the context. This makes it hard to find the signal
3 # in the backtrace and adds debugging time. With a BacktraceCleaner, you can setup filters and silencers for your particular
4 # context, so only the relevant lines are included.
5 #
6 # If you need to reconfigure an existing BacktraceCleaner, like the one in Rails, to show as much as possible, you can always
7 # call BacktraceCleaner#remove_silencers!
8 #
9 # Example:
10 #
11 # bc = BacktraceCleaner.new
12 # bc.add_filter { |line| line.gsub(Rails.root, '') }
13 # bc.add_silencer { |line| line =~ /mongrel|rubygems/ }
14 # bc.clean(exception.backtrace) # will strip the Rails.root prefix and skip any lines from mongrel or rubygems
15 #
16 # Inspired by the Quiet Backtrace gem by Thoughtbot.
17 class BacktraceCleaner
18 def initialize
19 @filters, @silencers = [], []
20 end
21
22 # Returns the backtrace after all filters and silencers has been run against it. Filters run first, then silencers.
23 def clean(backtrace)
24 silence(filter(backtrace))
25 end
26
27 # Adds a filter from the block provided. Each line in the backtrace will be mapped against this filter.
28 #
29 # Example:
30 #
31 # # Will turn "/my/rails/root/app/models/person.rb" into "/app/models/person.rb"
32 # backtrace_cleaner.add_filter { |line| line.gsub(Rails.root, '') }
33 def add_filter(&block)
34 @filters << block
35 end
36
37 # Adds a silencer from the block provided. If the silencer returns true for a given line, it'll be excluded from the
38 # clean backtrace.
39 #
40 # Example:
41 #
42 # # Will reject all lines that include the word "mongrel", like "/gems/mongrel/server.rb" or "/app/my_mongrel_server/rb"
43 # backtrace_cleaner.add_silencer { |line| line =~ /mongrel/ }
44 def add_silencer(&block)
45 @silencers << block
46 end
47
48 # Will remove all silencers, but leave in the filters. This is useful if your context of debugging suddenly expands as
49 # you suspect a bug in the libraries you use.
50 def remove_silencers!
51 @silencers = []
52 end
53
54
55 private
56 def filter(backtrace)
57 @filters.each do |f|
58 backtrace = backtrace.map { |line| f.call(line) }
59 end
60
61 backtrace
62 end
63
64 def silence(backtrace)
65 @silencers.each do |s|
66 backtrace = backtrace.reject { |line| s.call(line) }
67 end
68
69 backtrace
70 end
71 end
72 end