首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

TracePoint

Parent:Object

一个在良好的面向对象API中提供Kernel#set_trace_func功能的类。

示例

我们可以使用TracePoint专门收集异常信息:

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
trace.disable

请参阅TracePoint的活动以了解可能发生的事件和更多信息。

必须给出一个块,否则会引发一个ThreadError。

如果跟踪方法未包含在给定的事件过滤器中,则会引发RuntimeError。

代码语言:javascript
复制
TracePoint.trace(:line) do |tp|
    p tp.raised_exception
end
#=> RuntimeError: 'raised_exception' not supported by this event

如果在块外调用跟踪方法,则会引发RuntimeError。

代码语言:javascript
复制
TracePoint.trace(:line) do |tp|
  $tp = tp
end
$tp.line #=> access from outside (RuntimeError)

从其他线程访问也被禁止。

代码语言:javascript
复制
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本身。

代码语言:javascript
复制
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的便捷方法,可以自动激活跟踪。

代码语言:javascript
复制
trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
#=> #<TracePoint:enabled>

trace.enabled? #=> true
代码语言:javascript
复制
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

从事件返回生成的绑定对象

代码语言:javascript
复制
static VALUE
tracepoint_attr_binding(VALUE tpval)
{
    return rb_tracearg_binding(get_trace_arg());
}

callee_id() Show source

返回被调用方法的被调用名称

代码语言:javascript
复制
static VALUE
tracepoint_attr_callee_id(VALUE tpval)
{
    return rb_tracearg_callee_id(get_trace_arg());
}

defined_class() Show source

返回被调用方法的类或模块。

代码语言:javascript
复制
class C; def foo; end; end
trace = TracePoint.new(:call) do |tp|
  p tp.defined_class #=> C
end.enable do
  C.new.foo
end

如果方法由模块定义,则返回该模块。

代码语言:javascript
复制
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 之间的区别。

代码语言:javascript
复制
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
代码语言:javascript
复制
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。

代码语言:javascript
复制
trace.enabled?       #=> true
trace.disable        #=> false (previous status)
trace.enabled?       #=> false
trace.disable        #=> false

如果给出了一个块,那么只会在该块的范围内禁用跟踪。

代码语言:javascript
复制
trace.enabled?
#=> true

trace.disable do
    trace.enabled?
    # only disabled for this block
end

trace.enabled?
#=> true

注意:您不能访问块内的事件挂钩。

代码语言:javascript
复制
trace.disable { p tp.lineno }
#=> RuntimeError: access from outside
代码语言:javascript
复制
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。

代码语言:javascript
复制
trace.enabled?  #=> false
trace.enable    #=> false (previous state)
                #   trace is enabled
trace.enabled?  #=> true
trace.enable    #=> true (previous state)
                #   trace is still enabled

如果给出了一个块,跟踪将只在该块的范围内启用。

代码语言:javascript
复制
trace.enabled?
#=> false

trace.enable do
    trace.enabled?
    # only enabled for this block
end

trace.enabled?
#=> false

注意:您不能访问块内的事件挂钩。

代码语言:javascript
复制
trace.enable { p tp.lineno }
#=> RuntimeError: access from outside
代码语言:javascript
复制
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

跟踪的当前状态

代码语言:javascript
复制
VALUE
rb_tracepoint_enabled_p(VALUE tpval)
{
    rb_tp_t *tp = tpptr(tpval);
    return tp->tracing ? Qtrue : Qfalse;
}

event() Show source

事件类型

请参阅TracePoint事件以获取更多信息。

代码语言:javascript
复制
static VALUE
tracepoint_attr_event(VALUE tpval)
{
    return rb_tracearg_event(get_trace_arg());
}

inspect → string Show source

返回一个包含人类可读的TracePoint状态的字符串。

代码语言:javascript
复制
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

活动的行号

代码语言:javascript
复制
static VALUE
tracepoint_attr_lineno(VALUE tpval)
{
    return rb_tracearg_lineno(get_trace_arg());
}

method_id() Show source

在被调用方法的定义处返回名称

代码语言:javascript
复制
static VALUE
tracepoint_attr_method_id(VALUE tpval)
{
    return rb_tracearg_method_id(get_trace_arg());
}

path() Show source

正在运行的文件的路径

代码语言:javascript
复制
static VALUE
tracepoint_attr_path(VALUE tpval)
{
    return rb_tracearg_path(get_trace_arg());
}

raised_exception() Show source

来自:raise事件的异常值

代码语言:javascript
复制
static VALUE
tracepoint_attr_raised_exception(VALUE tpval)
{
    return rb_tracearg_raised_exception(get_trace_arg());
}

return_value() Show source

返回值从:returnc_returnb_return事件

代码语言:javascript
复制
static VALUE
tracepoint_attr_return_value(VALUE tpval)
{
    return rb_tracearg_return_value(get_trace_arg());
}

self() Show source

在事件期间返回跟踪对象

与#binding相同:

代码语言:javascript
复制
trace.binding.eval('self')
代码语言:javascript
复制
static VALUE
tracepoint_attr_self(VALUE tpval)
{
    return rb_tracearg_self(get_trace_arg());
}

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com