如何在Ruby中获取堆栈跟踪对象?

72

我需要在Ruby中获取一个堆栈跟踪对象,而不是将其打印出来,只是为了进行一些记录和转储以供后续分析。这可能吗?怎么做?

6个回答

92
你可以使用 Kernel.caller 来做到这一点。在生成异常堆栈跟踪时也使用相同的方法。
来自文档:
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"]

47

尝试

Thread.current.backtrace.join("\n")

12

尝试使用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

产生:

prog.rb:2:in `a'
prog.rb:6:in `b'
prog.rb:10

我想我必须抛出一个异常才能获取堆栈跟踪。 - pupeno
@J. Pablo 看起来是这样。如果您找到直接获取它的方法,请在此处发布。 - Nikita Rybak
1
Sven用Kernel.caller做得很好。 - pupeno

11
对于 Ruby 2.0+,您可以使用 Kernel#caller_locations。它基本上与Kernel#caller相同(在Sven Koschnicke的答案中有介绍),只是它返回一个Thread :: Backtrace :: Location 对象数组,而不是字符串数组。Thread :: Backtrace :: Location 提供了一些方法,例如pathlinenobase_label,当您需要访问关于堆栈跟踪的特定细节而不仅仅是原始字符串时,这些方法可能很有用。
文档中了解更多:

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

caller_locations(range) → array or nil

返回包含回溯位置对象的数组,表示当前执行堆栈。

有关详细信息,请参见Thread :: Backtrace :: Location

可选的 start 参数确定要从堆栈顶部忽略的初始堆栈条目数。

第二个可选的 length 参数可用于限制从堆栈中返回的条目数量。

如果 start 大于当前执行堆栈的大小,则返回 nil

还可以传递范围,它将返回包含指定范围内条目的数组。

使用示例:
def a
  caller_locations(0)
end
def b
  a
end
def c
  b
end

c.map(&:base_label)
#=> ["a", "b", "c", "<main>"]

7
Thread.current.backtrace

这将给你一个包含任何常规回溯中可能出现的所有行的数组。

3

如果你愿意,你也可以创建你自己的模块。正如Russ Olsen在Eloquent Ruby一书中所示:

# 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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接