How to get a stack trace object in Ruby?

后端 未结 6 1424
感情败类
感情败类 2020-12-13 08:34

I need to get a stack trace object in Ruby; not to print it, just to get it to do some recording and dumping for later analysis. Is that possible? How?

相关标签:
6条回答
  • 2020-12-13 08:44

    You can use Kernel.caller for this. The same method is used when generating stack traces for exceptions.

    From the docs:

    def a(skip)
      caller(skip)
    end
    def b(skip)
      a(skip)
    end
    def c(skip)
      b(skip)
    end
    c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
    c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
    c(2) #=> ["prog:8:in `c'", "prog:12"]
    c(3) #=> ["prog:13"]
    
    0 讨论(0)
  • 2020-12-13 08:51

    Try

    Thread.current.backtrace.join("\n")
    
    0 讨论(0)
  • 2020-12-13 08:52

    For Ruby 2.0+, you can use Kernel#caller_locations. It is essentially the same as Kernel#caller (covered in Sven Koschnicke's answer), except that instead of returning an array of strings, it returns an array of Thread::Backtrace::Location objects. Thread::Backtrace::Location provides methods such as path, lineno, and base_label, which may be useful when you need access to specific details about the stack trace, and not just a raw string.

    From the docs:

    caller_locations(start=1, length=nil) → array or nil

    caller_locations(range) → array or nil

    Returns the current execution stack—an array containing backtrace location objects.

    See Thread::Backtrace::Location for more information.

    The optional start parameter determines the number of initial stack entries to omit from the top of the stack.

    A second optional length parameter can be used to limit how many entries are returned from the stack.

    Returns nil if start is greater than the size of current execution stack.

    Optionally you can pass a range, which will return an array containing the entries within the specified range.

    Usage example:

    def a
      caller_locations(0)
    end
    def b
      a
    end
    def c
      b
    end
    
    c.map(&:base_label)
    #=> ["a", "b", "c", "<main>"]
    
    0 讨论(0)
  • 2020-12-13 08:55
    Thread.current.backtrace
    

    This will give you an array which contains all the lines that you may get in any normal backtrace.

    0 讨论(0)
  • 2020-12-13 08:59

    You can create your own if you want as well. As demonstrated in Eloquent Ruby by Russ Olsen:

    # define a proc to use that will handle your trace 
    proc_object = proc do |event, file, line, id, binding, klass| 
      puts "#{event} in #{file}/#{line} #{id} #{klass}"
    end 
    
    # tell Ruby to use your proc on traceable events
    set_trace_func(proc_object)
    
    0 讨论(0)
  • 2020-12-13 09:06

    Try error.backtrace:

    # Returns any backtrace associated with the exception.  
    # The backtrace is an array of strings, each containing either ``filename:lineNo: in `method’’’ or ``filename:lineNo.’‘
    
    def a
      raise "boom"
    end
    
    def b
      a()
    end
    
    begin
      b()
    rescue => detail
      print detail.backtrace.join("\n")
    end
    

    produces:

    prog.rb:2:in `a'
    prog.rb:6:in `b'
    prog.rb:10
    
    0 讨论(0)
提交回复
热议问题