TracePoint
class TracePoint
Parent:Object
一个在良好的面向对象API中提供Kernel#set_trace_func功能的类。
示例
我们可以使用TracePoint专门收集异常信息:
trace = TracePoint.new(:raise) do |tp|
p [tp.lineno, tp.event, tp.raised_exception]
end
#=> #<TracePoint:disabled>
trace.enable
#=> false
0 / 0
#=> [5, :raise, #<ZeroDivisionError: divided by 0>]
事件
如果您未指定要侦听的事件类型,则TracePoint将包含所有可用事件。
请注意
,不要依赖当前的事件集,因为此列表可能会更改。相反,建议您指定要使用的事件类型。
要过滤所追踪的内容,您可以将以下任何内容传递给events
:
:line
在新行上执行代码
:class
启动一个类或模块定义
:end
完成一个类或模块的定义
:call
调用Ruby方法
:return
从Ruby方法返回
:c_call
调用一个C语言例程
:c_return
从C语言例程返回
:raise
引发异常
:b_call
事件挂钩在块入口处
:b_return
在块结尾的事件挂钩
:thread_begin
线程开始处的事件挂钩
:thread_end
线程结束时的事件挂钩
:fiber_switch
光纤交换机上的事件挂钩
公共类别方法
new(*events) { |obj| block } → obj Show source
返回一个新的TracePoint对象,默认情况下不启用。
接下来,为了激活跟踪,你必须使用#enable
trace = TracePoint.new(:call) do |tp|
p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
end
#=> #<TracePoint:disabled>
trace.enable
#=> false
puts "Hello, TracePoint!"
# ...
# [48, IRB::Notifier::AbstractNotifier, :printf, :call]
# ...
如果要停用跟踪,则必须使用#disable
trace.disable
请参阅TracePoint的活动以了解可能发生的事件和更多信息。
必须给出一个块,否则会引发一个ThreadError。
如果跟踪方法未包含在给定的事件过滤器中,则会引发RuntimeError。
TracePoint.trace(:line) do |tp|
p tp.raised_exception
end
#=> RuntimeError: 'raised_exception' not supported by this event
如果在块外调用跟踪方法,则会引发RuntimeError。
TracePoint.trace(:line) do |tp|
$tp = tp
end
$tp.line #=> access from outside (RuntimeError)
从其他线程访问也被禁止。
static VALUE
tracepoint_new_s(int argc, VALUE *argv, VALUE self)
{
rb_event_flag_t events = 0;
int i;
if (argc > 0) {
for (i=0; i<argc; i++) {
events |= symbol2event_flag(argv[i]
}
}
else {
events = RUBY_EVENT_TRACEPOINT_ALL;
}
if (!rb_block_given_p()) {
rb_raise(rb_eThreadError, "must be called with a block"
}
return tracepoint_new(self, 0, events, 0, 0, rb_block_proc()
}
stat → obj Show source
返回TracePoint的内部信息。
返回值的内容是特定于实现的。将来可能会改变。
此方法仅用于调试TracePoint本身。
static VALUE
tracepoint_stat_s(VALUE self)
{
rb_vm_t *vm = GET_VM(
VALUE stat = rb_hash_new(
tracepoint_stat_event_hooks(stat, vm->self, vm->event_hooks.hooks
/* TODO: thread local hooks */
return stat;
}
trace(*events) { |obj| block } → obj Show source
::new的便捷方法,可以自动激活跟踪。
trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
#=> #<TracePoint:enabled>
trace.enabled? #=> true
static VALUE
tracepoint_trace_s(int argc, VALUE *argv, VALUE self)
{
VALUE trace = tracepoint_new_s(argc, argv, self
rb_tracepoint_enable(trace
return trace;
}
公共实例方法
binding() Show source
从事件返回生成的绑定对象
static VALUE
tracepoint_attr_binding(VALUE tpval)
{
return rb_tracearg_binding(get_trace_arg()
}
callee_id() Show source
返回被调用方法的被调用名称
static VALUE
tracepoint_attr_callee_id(VALUE tpval)
{
return rb_tracearg_callee_id(get_trace_arg()
}
defined_class() Show source
返回被调用方法的类或模块。
class C; def foo; end; end
trace = TracePoint.new(:call) do |tp|
p tp.defined_class #=> C
end.enable do
C.new.foo
end
如果方法由模块定义,则返回该模块。
module M; def foo; end; end
class C; include M; end;
trace = TracePoint.new(:call) do |tp|
p tp.defined_class #=> M
end.enable do
C.new.foo
end
注意:
defined_class返回单例类。
Kernel#set_trace_func的第6个块参数传递由singleton类附加的原始类。
这是
Kernel#set_trace_func
和
TracePoint 之间的区别。
class C; def self.foo; end; end
trace = TracePoint.new(:call) do |tp|
p tp.defined_class #=> #<Class:C>
end.enable do
C.foo
end
static VALUE
tracepoint_attr_defined_class(VALUE tpval)
{
return rb_tracearg_defined_class(get_trace_arg()
}
disable → true or false Show source
disable { block } → obj
取消激活跟踪
如果跟踪已启用,则返回true。如果跟踪被禁用,则返回false。
trace.enabled? #=> true
trace.disable #=> false (previous status)
trace.enabled? #=> false
trace.disable #=> false
如果给出了一个块,那么只会在该块的范围内禁用跟踪。
trace.enabled?
#=> true
trace.disable do
trace.enabled?
# only disabled for this block
end
trace.enabled?
#=> true
注意:您不能访问块内的事件挂钩。
trace.disable { p tp.lineno }
#=> RuntimeError: access from outside
static VALUE
tracepoint_disable_m(VALUE tpval)
{
rb_tp_t *tp = tpptr(tpval
int previous_tracing = tp->tracing;
rb_tracepoint_disable(tpval
if (rb_block_given_p()) {
return rb_ensure(rb_yield, Qnil,
previous_tracing ? rb_tracepoint_enable : rb_tracepoint_disable,
tpval
}
else {
return previous_tracing ? Qtrue : Qfalse;
}
}
enable → true or false Show source
enable { block } → obj
激活跟踪
如果跟踪已启用,则返回true。如果跟踪被禁用,则返回false。
trace.enabled? #=> false
trace.enable #=> false (previous state)
# trace is enabled
trace.enabled? #=> true
trace.enable #=> true (previous state)
# trace is still enabled
如果给出了一个块,跟踪将只在该块的范围内启用。
trace.enabled?
#=> false
trace.enable do
trace.enabled?
# only enabled for this block
end
trace.enabled?
#=> false
注意:您不能访问块内的事件挂钩。
trace.enable { p tp.lineno }
#=> RuntimeError: access from outside
static VALUE
tracepoint_enable_m(VALUE tpval)
{
rb_tp_t *tp = tpptr(tpval
int previous_tracing = tp->tracing;
rb_tracepoint_enable(tpval
if (rb_block_given_p()) {
return rb_ensure(rb_yield, Qnil,
previous_tracing ? rb_tracepoint_enable : rb_tracepoint_disable,
tpval
}
else {
return previous_tracing ? Qtrue : Qfalse;
}
}
enabled? → true or false Show source
跟踪的当前状态
VALUE
rb_tracepoint_enabled_p(VALUE tpval)
{
rb_tp_t *tp = tpptr(tpval
return tp->tracing ? Qtrue : Qfalse;
}
event() Show source
事件类型
请参阅TracePoint事件以获取更多信息。
static VALUE
tracepoint_attr_event(VALUE tpval)
{
return rb_tracearg_event(get_trace_arg()
}
inspect → string Show source
返回一个包含人类可读的TracePoint状态的字符串。
static VALUE
tracepoint_inspect(VALUE self)
{
rb_tp_t *tp = tpptr(self
rb_trace_arg_t *trace_arg = GET_THREAD()->trace_arg;
if (trace_arg) {
switch (trace_arg->event) {
case RUBY_EVENT_LINE:
case RUBY_EVENT_SPECIFIED_LINE:
{
VALUE sym = rb_tracearg_method_id(trace_arg
if (NIL_P(sym))
goto default_inspect;
return rb_sprintf("#<TracePoint:%"PRIsVALUE"@%"PRIsVALUE":%d in `%"PRIsVALUE"'>",
rb_tracearg_event(trace_arg),
rb_tracearg_path(trace_arg),
FIX2INT(rb_tracearg_lineno(trace_arg)),
sym
}
case RUBY_EVENT_CALL:
case RUBY_EVENT_C_CALL:
case RUBY_EVENT_RETURN:
case RUBY_EVENT_C_RETURN:
return rb_sprintf("#<TracePoint:%"PRIsVALUE" `%"PRIsVALUE"'@%"PRIsVALUE":%d>",
rb_tracearg_event(trace_arg),
rb_tracearg_method_id(trace_arg),
rb_tracearg_path(trace_arg),
FIX2INT(rb_tracearg_lineno(trace_arg))
case RUBY_EVENT_THREAD_BEGIN:
case RUBY_EVENT_THREAD_END:
return rb_sprintf("#<TracePoint:%"PRIsVALUE" %"PRIsVALUE">",
rb_tracearg_event(trace_arg),
rb_tracearg_self(trace_arg)
default:
default_inspect:
return rb_sprintf("#<TracePoint:%"PRIsVALUE"@%"PRIsVALUE":%d>",
rb_tracearg_event(trace_arg),
rb_tracearg_path(trace_arg),
FIX2INT(rb_tracearg_lineno(trace_arg))
}
}
else {
return rb_sprintf("#<TracePoint:%s>", tp->tracing ? "enabled" : "disabled"
}
}
lineno() Show source
活动的行号
static VALUE
tracepoint_attr_lineno(VALUE tpval)
{
return rb_tracearg_lineno(get_trace_arg()
}
method_id() Show source
在被调用方法的定义处返回名称
static VALUE
tracepoint_attr_method_id(VALUE tpval)
{
return rb_tracearg_method_id(get_trace_arg()
}
path() Show source
正在运行的文件的路径
static VALUE
tracepoint_attr_path(VALUE tpval)
{
return rb_tracearg_path(get_trace_arg()
}
raised_exception() Show source
来自:raise
事件的异常值
static VALUE
tracepoint_attr_raised_exception(VALUE tpval)
{
return rb_tracearg_raised_exception(get_trace_arg()
}
return_value() Show source
返回值从:return
,c_return
和b_return
事件
static VALUE
tracepoint_attr_return_value(VALUE tpval)
{
return rb_tracearg_return_value(get_trace_arg()
}
self() Show source
在事件期间返回跟踪对象
与#binding相同:
trace.binding.eval('self')
static VALUE
tracepoint_attr_self(VALUE tpval)
{
return rb_tracearg_self(get_trace_arg()
}