require 'epitools' # TODO: Pick a backtrace format. (Also, add a method to replace default backtracer.) # TODO: This chould be in a class. class Line # :nodoc: attr_accessor :path, :num, :meth, :dir, :filename def initialize(path, num, meth) @path = path @num = num @meth = meth @gem = false @dir, @filename = File.split(path) if @dir =~ %r{^/usr/lib/ruby/gems/1.8/gems/(.+)} @dir = "[gem] #{$1}" @gem = true end end def gem? @gem end def codeline l = @num.to_i - 1 open(path).readlines[l] end end def parse_lines(backtrace) backtrace.map do |line| case line when /^\s+(.+):(\d+):in \`(.+)'/ Line.new($1, $2, $3) when /^\s+(.+):(\d+)/ Line.new($1, $2, '') when /^\s+$/ next else raise "huh?!" end end.compact end def color_backtrace_1(lines) groups = lines.split_before { |line,nextline| line.path != nextline.path } for group in groups dir, filename = File.split(group.first.path) puts "#{filename.green} (#{dir.light_white})" # /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb # 234: require | 553: new_constants_in | group.each do |line| puts " |_ #{line.num.magenta}: #{line.meth.light_yellow.underline}" end #puts " |_ " + group.map{|line| "#{line.num.magenta}: #{line.meth.light_yellow}"}.join(' | '.red) end end def color_backtrace_2(lines, **options) groups = lines.reverse.split_at { |line,nextline| line.path != nextline.path } if options[:no_gems] groups = groups.split_when { |a, nexta| a.first.gem? != nexta.first.gem? } groups.map! { |group| group.first.gem? ? [] : group } end for group in groups if group.empty? puts " ... ignored ... " puts next end firstline = group.first # custom_require.rb (/usr/local/lib/site_ruby/1.8/rubygems) # 234: require => super # 553: new_constants_in => #puts "#{firstline.filename.green} (#{firstline.dir.light_white})" puts "#{firstline.filename.underline} (#{firstline.dir.light_white})" max_methsize = group.map { |line| line.meth.size}.max group.each do |line| pad = " " * (max_methsize - line.meth.size) puts " #{line.num.magenta}: #{line.meth.light_yellow}#{pad}" puts " #{"|_".blue} #{line.codeline.strip}" end puts end end def python_backtrace(lines) #groups = lines.reverse.split_when { |line,nextline| line.path != nextline.path } lines = lines.reverse puts "Traceback (most recent call last):" for line in lines puts %{ File "#{line.path}", line #{line.num}, in #{line.meth}} puts %{ #{line.codeline.strip}} end end def debug_backtrace(lines) lines.each do |line| p line.path end end if $0 == __FILE__ backtrace = %{ /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/attribute_methods.rb:256:in `method_missing' vendor/plugins/attribute_fu/lib/attribute_fu/associations.rb:28:in `method_missing' app/helpers/admin/products_helper.rb:17:in `description_column' vendor/plugins/active_scaffold/lib/helpers/list_column_helpers.rb:11:in `send' vendor/plugins/active_scaffold/lib/helpers/list_column_helpers.rb:11:in `get_column_value' vendor/plugins/active_scaffold/frontends/default/views/_list_record.rhtml:10:in `_run_erb_47vendor47plugins47active_scaffold47frontends47default47views47_list_record46rhtml' vendor/plugins/active_scaffold/lib/data_structures/action_columns.rb:68:in `each' vendor/plugins/active_scaffold/lib/data_structures/action_columns.rb:55:in `each' vendor/plugins/active_scaffold/frontends/default/views/_list_record.rhtml:9:in `_run_erb_47vendor47plugins47active_scaffold47frontends47default47views47_list_record46rhtml' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:338:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:338:in `execute' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template_handlers/compilable.rb:29:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template_handlers/compilable.rb:29:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partial_template.rb:20:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/benchmarking.rb:26:in `benchmark' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/core_ext/benchmark.rb:8:in `realtime' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/benchmarking.rb:26:in `benchmark' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partial_template.rb:19:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template.rb:22:in `render_template' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partial_template.rb:28:in `render_member' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partials.rb:142:in `render_partial_collection_with_known_partial_path' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partials.rb:141:in `map' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partials.rb:141:in `render_partial_collection_with_known_partial_path' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partials.rb:135:in `render_partial_collection' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:271:in `render_without_active_scaffold' vendor/plugins/active_scaffold/lib/extensions/action_view_rendering.rb:55:in `render_without_haml' /usr/lib/ruby/gems/1.8/gems/haml-2.0.2/lib/haml/helpers/action_view_mods.rb:6:in `render' vendor/plugins/active_scaffold/frontends/default/views/_list.rhtml:21:in `_run_erb_47vendor47plugins47active_scaffold47frontends47default47views47_list46rhtml' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:338:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:338:in `execute' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template_handlers/compilable.rb:29:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template_handlers/compilable.rb:29:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partial_template.rb:20:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/benchmarking.rb:26:in `benchmark' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/core_ext/benchmark.rb:8:in `realtime' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/benchmarking.rb:26:in `benchmark' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partial_template.rb:19:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template.rb:22:in `render_template' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/partials.rb:110:in `render_partial' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:273:in `render_without_active_scaffold' vendor/plugins/active_scaffold/lib/extensions/action_view_rendering.rb:55:in `render_without_haml' /usr/lib/ruby/gems/1.8/gems/haml-2.0.2/lib/haml/helpers/action_view_mods.rb:6:in `render' vendor/plugins/active_scaffold/frontends/default/views/list.rhtml:9:in `_run_erb_47vendor47plugins47active_scaffold47frontends47default47views47list46rhtml' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:338:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:338:in `execute' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template_handlers/compilable.rb:29:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template_handlers/compilable.rb:29:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template.rb:35:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/template.rb:22:in `render_template' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_view/base.rb:245:in `render_file' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:1108:in `render_for_file' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:865:in `render_with_no_layout' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:880:in `render_with_no_layout' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/layout.rb:251:in `render_without_benchmark' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/benchmarking.rb:51:in `render_without_active_scaffold' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/core_ext/benchmark.rb:8:in `realtime' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/benchmarking.rb:51:in `render_without_active_scaffold' vendor/plugins/active_scaffold/lib/extensions/action_controller_rendering.rb:13:in `render' vendor/plugins/active_scaffold/lib/actions/list.rb:37:in `list' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/mime_responds.rb:131:in `call' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/mime_responds.rb:131:in `custom' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/mime_responds.rb:160:in `call' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/mime_responds.rb:160:in `respond' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/mime_responds.rb:154:in `each' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/mime_responds.rb:154:in `respond' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/mime_responds.rb:107:in `respond_to' vendor/plugins/active_scaffold/lib/actions/list.rb:35:in `list' vendor/plugins/active_scaffold/lib/actions/list.rb:8:in `index' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:1162:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:1162:in `perform_action_without_filters' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/filters.rb:580:in `call_filters' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/filters.rb:573:in `perform_action_without_benchmark' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/rescue.rb:201:in `perform_action_without_caching' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/caching/sql_cache.rb:13:in `perform_action' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in `cache' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/query_cache.rb:8:in `cache' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/caching/sql_cache.rb:12:in `perform_action' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:529:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:529:in `process_without_filters' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/filters.rb:569:in `process_without_session_management_support' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/session_management.rb:130:in `sass_old_process' /usr/lib/ruby/gems/1.8/gems/haml-2.0.2/lib/sass/plugin/rails.rb:19:in `process' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:389:in `process' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:149:in `handle_request' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:107:in `dispatch' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:104:in `synchronize' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:104:in `dispatch' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi' /usr/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:35:in `dispatch' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:76:in `process' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:74:in `synchronize' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:74:in `process' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:in `process_client' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `each' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `process_client' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `initialize' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `new' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `initialize' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `new' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `run' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:282:in `run' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `each' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `run' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:128:in `run' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/command.rb:212:in `run' /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:281 /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:502:in `load' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:502:in `load' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:354:in `new_constants_in' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:502:in `load' /usr/lib/ruby/gems/1.8/gems/rails-2.1.0/lib/commands/servers/mongrel.rb:64 /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:509:in `require' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:354:in `new_constants_in' /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:509:in `require' /usr/lib/ruby/gems/1.8/gems/rails-2.1.0/lib/commands/server.rb:39 /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' script/server:3 }.lines begin String.new nil rescue => e backtrace = e.backtrace end lines = parse_lines(backtrace) #debug_backtrace(lines) #color_backtrace_1(lines) #python_backtrace(lines) color_backtrace_2(lines)#, :no_gems=>true) end