Module: BacktraceShortener
- Defined in:
- lib/backtrace_shortener.rb,
lib/backtrace_shortener/version.rb
Overview
This can patch the Exception class to prune the size of the backtraces and to make each line shorter. The idea is to improve the developer experience, because exceptions in apps using rbenv and gems can be taller than one terminal screen and each line can be long. See how painful this is with a 50 line backtrace:
...
/Users/philc/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/sequel-3.28.0/lib/sequel/adapters/mysql.rb:175:in `query'
/Users/philc/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/sequel-3.28.0/lib/sequel/adapters/mysql.rb:175:in `block in _execute'
...
To apply this patch, invoke BacktraceCleanear.monkey_patch_the_exception_class!
If you want to access the full backtrace while debugging, you can use my_exception.full_backtrace. If you want to write your own filter, append your own Proc to BacktraceShortener.filters:
BacktraceShortener.filters.unshift(Proc.new { |backtrace| backtrace[0, 10] }) # Shortens to 10 lines.
Constant Summary collapse
- VERSION =
"0.1.0"
Class Attribute Summary collapse
-
.filters ⇒ Object
Returns the value of attribute filters.
Class Method Summary collapse
-
.abbreviate_gem_directory_name(backtrace) ⇒ Object
Abbreviate any long gem paths, e.g.
-
.collapse_gems(backtrace) ⇒ Object
Backtraces which involve gems can include many lines from within the gem’s internals.
-
.gem_from_line(backtrace_line) ⇒ Object
Returns the gem in the given backtrace line, or nil if the line does not include a gem in it.
- .monkey_patch_the_exception_class! ⇒ Object
Class Attribute Details
.filters ⇒ Object
Returns the value of attribute filters.
67 68 69 |
# File 'lib/backtrace_shortener.rb', line 67 def filters @filters end |
Class Method Details
.abbreviate_gem_directory_name(backtrace) ⇒ Object
Abbreviate any long gem paths, e.g.
/Users/philc/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/sequel-3.28.0/lib
=> .../gems/1.9.1/gems/sequel-3.28.0/lib
33 34 35 36 37 |
# File 'lib/backtrace_shortener.rb', line 33 def self.abbreviate_gem_directory_name(backtrace) backtrace.map do |line| line.sub(Gem.dir, "...") end end |
.collapse_gems(backtrace) ⇒ Object
Backtraces which involve gems can include many lines from within the gem’s internals. This usually isn’t helpful. Collapse those long sequences of lines and include just the first and last line.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/backtrace_shortener.rb', line 41 def self.collapse_gems(backtrace) current_gem = nil current_gem_line_number = nil i = backtrace.size - 1 while i >= 0 line_gem = gem_from_line(backtrace[i]) if line_gem != current_gem || i == 0 if current_gem && (current_gem_line_number - i) > 2 backtrace[i..current_gem_line_number] = [backtrace[i], "<..>", backtrace[current_gem_line_number]] end current_gem = line_gem current_gem_line_number = i end i -= 1 end backtrace end |
.gem_from_line(backtrace_line) ⇒ Object
Returns the gem in the given backtrace line, or nil if the line does not include a gem in it.
61 62 63 64 |
# File 'lib/backtrace_shortener.rb', line 61 def self.gem_from_line(backtrace_line) # Pull out "sequel-3.28.0" from this path: ".../lib/ruby/gems/1.9.1/gems/sequel-3.28.0/lib/..." (%r{/ruby/gems/[^/]+/gems/([^/]+)/}.match(backtrace_line) || [])[1] end |
.monkey_patch_the_exception_class! ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/backtrace_shortener.rb', line 15 def self.monkey_patch_the_exception_class! return if Exception.new.respond_to?(:backtrace_prior_to_backtrace_shortener_monkey_patch) Exception.class_eval do alias :backtrace_prior_to_backtrace_shortener_monkey_patch :backtrace alias :full_backtrace :backtrace_prior_to_backtrace_shortener_monkey_patch def backtrace backtrace = backtrace_prior_to_backtrace_shortener_monkey_patch return nil if backtrace.nil? BacktraceShortener.filters.inject(backtrace) { |backtrace, filter| filter.call(backtrace) } end end end |