How do I get ruby to print a full backtrace instead of a truncated one?

前端 未结 10 1583
-上瘾入骨i
-上瘾入骨i 2020-12-12 12:00

When I get exceptions, it is often from deep within the call stack. When this happens, more often than not, the actual offending line of code is hidden from me:



        
相关标签:
10条回答
  • 2020-12-12 12:50

    You can also use backtrace Ruby gem (I'm the author):

    require 'backtrace'
    begin
      # do something dangerous
    rescue StandardError => e
      puts Backtrace.new(e)
    end
    
    0 讨论(0)
  • 2020-12-12 12:51

    I was getting these errors when trying to load my test environment (via rake test or autotest) and the IRB suggestions didn't help. I ended up wrapping my entire test/test_helper.rb in a begin/rescue block and that fixed things up.

    begin
      class ActiveSupport::TestCase
        #awesome stuff
      end
    rescue => e
      puts e.backtrace
    end
    
    0 讨论(0)
  • 2020-12-12 12:53

    This mimics the official Ruby trace, if that's important to you.

    begin
      0/0  # or some other nonsense
    rescue => e
      puts e.backtrace.join("\n\t")
           .sub("\n\t", ": #{e}#{e.class ? " (#{e.class})" : ''}\n\t")
    end
    

    Amusingly, it doesn't handle 'unhandled exception' properly, reporting it as 'RuntimeError', but the location is correct.

    0 讨论(0)
  • 2020-12-12 13:04

    [examine all threads backtraces to find the culprit]
    Even fully expanded call stack can still hide the actual offending line of code from you when you use more than one thread!

    Example: One thread is iterating ruby Hash, other thread is trying to modify it. BOOM! Exception! And the problem with the stack trace you get while trying to modify 'busy' hash is that it shows you chain of functions down to the place where you're trying to modify hash, but it does NOT show who's currently iterating it in parallel (who owns it)! Here's the way to figure that out by printing stack trace for ALL currently running threads. Here's how you do this:

    # This solution was found in comment by @thedarkone on https://github.com/rails/rails/issues/24627
    rescue Object => boom
    
        thread_count = 0
        Thread.list.each do |t|
          thread_count += 1
          err_msg += "--- thread #{thread_count} of total #{Thread.list.size} #{t.object_id} backtrace begin \n"
          # Lets see if we are able to pin down the culprit
          # by collecting backtrace for all existing threads:
          err_msg += t.backtrace.join("\n")
          err_msg += "\n---thread #{thread_count} of total #{Thread.list.size} #{t.object_id} backtrace end \n"
        end
    
        # and just print it somewhere you like:
        $stderr.puts(err_msg)
    
        raise # always reraise
    end
    

    The above code snippet is useful even just for educational purposes as it can show you (like x-ray) how many threads you actually have (versus how many you thought you have - quite often those two are different numbers ;)

    0 讨论(0)
提交回复
热议问题