Ruby 2.4

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

返回值从:returnc_returnb_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() }