class TracePoint - Documentation for Ruby 3.2

# class TracePoint

Document-class: `TracePoint`

A class that provides the functionality of `Kernel#set_trace_func` in a nice Object-Oriented API.

## Example¶ ↑

We can use `TracePoint` to gather information specifically for exceptions:

    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>]

## Events¶ ↑

If you don’t specify the type of events you want to listen for, `TracePoint` will include all available events.

Note do not depend on current event set, as this list is subject to change. Instead, it is recommended you specify the type of events you want to use.

To filter what is traced, you can pass any of the following as `events`:

`:line`

  execute an expression or statement on a new line

`:class`

  start a class or module definition

`:end`

  finish a class or module definition

`:call`

  call a Ruby method

`:return`

  return from a Ruby method

`:c_call`

  call a C-language routine

`:c_return`

  return from a C-language routine

`:raise`

  raise an exception

`:b_call`

  event hook at block entry

`:b_return`

  event hook at block ending

`:a_call`

  event hook at all calls (`call`, `b_call`, and `c_call`)

`:a_return`

  event hook at all returns (`return`, `b_return`, and `c_return`)

`:thread_begin`

  event hook at thread beginning

`:thread_end`

  event hook at thread ending

`:fiber_switch`

  event hook at fiber switch

`:script_compiled`

  new Ruby code compiled (with `eval`, `load` or `require`)

### Public Class Methods

allow_reentry { block } click to toggle source

In general, while a `TracePoint` callback is running, other registered callbacks are not called to avoid confusion by reentrance. This method allows the reentrance in a given block. This method should be used carefully, otherwise the callback can be easily called infinitely.

If this method is called when the reentrance is already allowed, it raises a `RuntimeError`.

Example:

    # Without reentry
    # ---------------

    line_handler = TracePoint.new(:line) do |tp|
      next if tp.path != __FILE__ # only work in this file
      puts "Line handler"
      binding.eval("class C; end")
    end.enable

    class_handler = TracePoint.new(:class) do |tp|
      puts "Class handler"
    end.enable

    class B
    end

    # This script will print "Class handler" only once: when inside :line
    # handler, all other handlers are ignored

    # With reentry
    # ------------

    line_handler = TracePoint.new(:line) do |tp|
      next if tp.path != __FILE__ # only work in this file
      next if (__LINE__..__LINE__+3).cover?(tp.lineno) # don't be invoked from itself
      puts "Line handler"
      TracePoint.allow_reentry { binding.eval("class C; end") }
    end.enable

    class_handler = TracePoint.new(:class) do |tp|
      puts "Class handler"
    end.enable

    class B
    end

    # This wil print "Class handler" twice: inside allow_reentry block in :line
    # handler, other handlers are enabled.

Note that the example shows the principal effect of the method, but its practical usage is for debugging libraries that sometimes require other libraries hooks to not be affected by debugger being inside trace point handling. Precautions should be taken against infinite recursion in this case (note that we needed to filter out calls by itself from :line handler, otherwise it will call itself infinitely).

    # File trace_point.rb, line 199
    def self.allow_reentry
      Primitive.tracepoint_allow_reentry
    end

new(*events) { |obj| block } → obj click to toggle source

Returns a new `TracePoint` object, not enabled by default.

Next, in order to activate the trace, you must use `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]
    # ...

When you want to deactivate the trace, you must use `TracePoint#disable`

    trace.disable

See Events at `TracePoint` for possible events and more information.

A block must be given, otherwise an `ArgumentError` is raised.

If the trace method isn’t included in the given events filter, a `RuntimeError` is raised.

    TracePoint.trace(:line) do |tp|
        p tp.raised_exception
    end
    #=> RuntimeError: 'raised_exception' not supported by this event

If the trace method is called outside block, a `RuntimeError` is raised.

    TracePoint.trace(:line) do |tp|
      $tp = tp
    end
    $tp.lineno #=> access from outside (RuntimeError)

Access from other threads is also forbidden.

    # File trace_point.rb, line 97
    def self.new(*events)
      Primitive.tracepoint_new_s(events)
    end

stat → obj click to toggle source

Returns internal information of `TracePoint`.

The contents of the returned value are implementation specific. It may be changed in future.

This method is only for debugging `TracePoint` itself.

    # File trace_point.rb, line 119
    def self.stat
      Primitive.tracepoint_stat_s
    end

trace(*events) { |obj| block } → obj click to toggle source

A convenience method for `TracePoint.new`, that activates the trace automatically.

    trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
    #=> #<TracePoint:enabled>

    trace.enabled? #=> true

    # File trace_point.rb, line 134
    def self.trace(*events)
      Primitive.tracepoint_trace_s(events)
    end

### Public Instance Methods

binding() click to toggle source

Return the generated binding object from event.

Note that for `c_call` and `c_return` events, the binding returned is the binding of the nearest Ruby method calling the C method, since C methods themselves do not have bindings.

    # File trace_point.rb, line 383
    def binding
      Primitive.tracepoint_attr_binding
    end

callee_id() click to toggle source

Return the called name of the method being called

    # File trace_point.rb, line 338
    def callee_id
      Primitive.tracepoint_attr_callee_id
    end

defined_class() click to toggle source

Return class or module of the method being called.

    class C; def foo; end; end
    trace = TracePoint.new(:call) do |tp|
      p tp.defined_class #=> C
    end.enable do
      C.new.foo
    end

If method is defined by a module, then that module is returned.

    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

Note: `defined_class` returns singleton class.

6th block parameter of `Kernel#set_trace_func` passes original class of attached by singleton class.

This is a difference between Kernel#set_trace_func and 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

    # File trace_point.rb, line 374
    def defined_class
      Primitive.tracepoint_attr_defined_class
    end

disable → true or false click to toggle source
disable { block } → obj

Deactivates the trace

Return true if trace was enabled. Return false if trace was disabled.

    trace.enabled?      #=> true
    trace.disable       #=> true (previous status)
    trace.enabled?      #=> false
    trace.disable       #=> false

If a block is given, the trace will only be disable within the scope of the block.

    trace.enabled?
    #=> true

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

    trace.enabled?
    #=> true

Note: You cannot access event hooks within the block.

    trace.disable { p tp.lineno }
    #=> RuntimeError: access from outside

    # File trace_point.rb, line 297
    def disable
      Primitive.tracepoint_disable_m
    end

enable(target: nil, target_line: nil, target_thread: nil) → true or false click to toggle source
enable(target: nil, target_line: nil, target_thread: :default) { block } → obj

Activates the trace.

Returns `true` if trace was enabled. Returns `false` if trace was disabled.

    trace.enabled?  #=> false
    trace.enable    #=> false (previous state)
                    #   trace is enabled
    trace.enabled?  #=> true
    trace.enable    #=> true (previous state)
                    #   trace is still enabled

If a block is given, the trace will only be enabled during the block call. If target and target_line are both nil, then target_thread will default to the current thread if a block is given.

    trace.enabled?
    #=> false

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

    trace.enabled?
    #=> false

`target`, `target_line` and `target_thread` parameters are used to limit tracing only to specified code objects. `target` should be a code object for which `RubyVM::InstructionSequence.of` will return an instruction sequence.

    t = TracePoint.new(:line) { |tp| p tp }

    def m1
      p 1
    end

    def m2
      p 2
    end

    t.enable(target: method(:m1))

    m1
    # prints #<TracePoint:line test.rb:4 in `m1'>
    m2
    # prints nothing

Note: You cannot access event hooks within the `enable` block.

    trace.enable { p tp.lineno }
    #=> RuntimeError: access from outside

    # File trace_point.rb, line 261
    def enable(target: nil, target_line: nil, target_thread: :default)
      Primitive.tracepoint_enable_m(target, target_line, target_thread)
    end

enabled? → true or false click to toggle source

The current status of the trace

    # File trace_point.rb, line 305
    def enabled?
      Primitive.tracepoint_enabled_p
    end

eval_script() click to toggle source

Compiled source code (`String`) on *eval methods on the `:script_compiled` event. If loaded from a file, it will return nil.

    # File trace_point.rb, line 409
    def eval_script
      Primitive.tracepoint_attr_eval_script
    end

event() click to toggle source

Type of event

See Events at `TracePoint` for more information.

    # File trace_point.rb, line 312
    def event
      Primitive.tracepoint_attr_event
    end

inspect → string click to toggle source

Return a string containing a human-readable `TracePoint` status.

    # File trace_point.rb, line 106
    def inspect
      Primitive.tracepoint_inspect
    end

instruction_sequence() click to toggle source

Compiled instruction sequence represented by a `RubyVM::InstructionSequence` instance on the `:script_compiled` event.

Note that this method is MRI specific.

    # File trace_point.rb, line 417
    def instruction_sequence
      Primitive.tracepoint_attr_instruction_sequence
    end

lineno() click to toggle source

Line number of the event

    # File trace_point.rb, line 317
    def lineno
      Primitive.tracepoint_attr_lineno
    end

method_id() click to toggle source

Return the name at the definition of the method being called

    # File trace_point.rb, line 333
    def method_id
      Primitive.tracepoint_attr_method_id
    end

parameters() click to toggle source

Return the parameters definition of the method or block that the current hook belongs to. Format is the same as for `Method#parameters`

    # File trace_point.rb, line 328
    def parameters
      Primitive.tracepoint_attr_parameters
    end

path() click to toggle source

Path of the file being run

    # File trace_point.rb, line 322
    def path
      Primitive.tracepoint_attr_path
    end

raised_exception() click to toggle source

Value from exception raised on the `:raise` event

    # File trace_point.rb, line 403
    def raised_exception
      Primitive.tracepoint_attr_raised_exception
    end

return_value() click to toggle source

Return value from `:return`, `c_return`, and `b_return` event

    # File trace_point.rb, line 398
    def return_value
      Primitive.tracepoint_attr_return_value
    end

self() click to toggle source

Return the trace object during event

Same as the following, except it returns the correct object (the method receiver) for `c_call` and `c_return` events:

    trace.binding.eval('self')

    # File trace_point.rb, line 393
    def self
      Primitive.tracepoint_attr_self
    end