Spec-Zone.ru › Ruby 3.3

класс TracePoint

Родитель:
Объект

Класс, предоставляющий функциональность Kernel#set_trace_func в удобном объектно-ориентированном API.

Пример

Мы можем использовать 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

выброс исключения

:rescue

обработка исключения

:b_call

событие хук при входе в блок

:b_return

событие хук при выходе из блока

:a_call

событие хук при всех вызовах (call, b_call, и c_call)

:a_return

событие хук при всех возвратах (return, b_return, и c_return)

:thread_begin

событие хук при начале потока

:thread_end

событие хук при завершении потока

:fiber_switch

событие хук при переключении волокна

:script_compiled

компиляция нового кода Ruby (с eval, load или require)

Публичные методы класса

allow_reentry { блок } Показать исходный код
# File trace_point.rb, line 198
def self.allow_reentry
  Primitive.tracepoint_allow_reentry
end

В общем случае, когда обратный вызов TracePoint выполняется, другие зарегистрированные обратные вызовы не вызываются, чтобы избежать путаницы из-за повторного входа. Этот метод позволяет повторный вход в заданном блоке. Этот метод следует использовать с осторожностью, в противном случае обратный вызов может быть вызван бесконечно.

Если этот метод вызывается, когда повторный вход уже разрешен, он генерирует исключение RuntimeError.

Пример:

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

Обратите внимание, что пример демонстрирует основной эффект метода, но его практическое применение предназначено для отладки библиотек, которые иногда требуют, чтобы другие библиотечные хуки не затрагивались, когда отладчик находится внутри обработки события трассировки. В этом случае следует принять меры предосторожности против бесконечной рекурсии (обратите внимание, что нам нужно было отфильтровать вызовы самого себя из обработчика :line, иначе он будет вызывать себя бесконечно).

new(*events) { |obj| блок } → obj Показать исходный код
# File trace_point.rb, line 96
def self.new(*events)
  Primitive.tracepoint_new_s(events)
end

Возвращает новый объект TracePoint, по умолчанию не активированный.

Далее, для активации трассировки, необходимо использовать 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]
# ...

Для деактивации трассировки необходимо использовать TracePoint#disable

trace.disable

См. События на TracePoint для возможных событий и дополнительной информации.

Блок должен быть задан, в противном случае генерируется исключение ArgumentError.

Если метод трассировки не включен в заданный фильтр событий, генерируется исключение 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.lineno #=> access from outside (RuntimeError)

Доступ из других потоков также запрещён.

stat → obj Показать исходный код
# File trace_point.rb, line 118
def self.stat
  Primitive.tracepoint_stat_s
end

Возвращает внутреннюю информацию о TracePoint.

Содержимое возвращаемого значения зависит от реализации. Оно может изменяться в будущем.

Этот метод предназначен только для отладки TracePoint самого.

trace(*events) { |obj| блок } → obj Показать исходный код
# File trace_point.rb, line 133
def self.trace(*events)
  Primitive.tracepoint_trace_s(events)
end

Удобный метод для TracePoint.new, автоматически активирующий трассировку.

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

trace.enabled? #=> true

Общедоступные методы экземпляров

binding() Показать исходный код
# File trace_point.rb, line 381
def binding
  Primitive.tracepoint_attr_binding
end

Возвращает сгенерированный объект привязки из события.

Обратите внимание, что для событий :c_call и :c_return метод вернёт nil, так как у самих C-методов нет привязок.

callee_id() Показать исходный код
# File trace_point.rb, line 337
def callee_id
  Primitive.tracepoint_attr_callee_id
end

Возвращает имя вызываемого метода.

defined_class() Показать исходный код
# File trace_point.rb, line 373
def defined_class
  Primitive.tracepoint_attr_defined_class
end

Возвращает класс или модуль вызываемого метода.

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 возвращает единственный класс.

6-й параметр блока Kernel#set_trace_func передаёт исходный класс, прикреплённый к классу-синглтону.

Различие между 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
disable → true или false Показать исходный код
disable { блок } → obj
# File trace_point.rb, line 296
def disable
  Primitive.tracepoint_disable_m
end

Деактивирует трассировку.

Возвращает true, если трассировка была включена. Возвращает false, если трассировка была отключена.

trace.enabled?      #=> true
trace.disable       #=> true (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
enable(target: nil, target_line: nil, target_thread: nil) → true или false Показать исходный код
enable(target: nil, target_line: nil, target_thread: :default) { блок } → obj
# File trace_point.rb, line 260
def enable(target: nil, target_line: nil, target_thread: :default)
  Primitive.tracepoint_enable_m(target, target_line, target_thread)
end

Включает трассировку.

Возвращает 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

Если указан блок, трассировка будет включена только во время выполнения блока. Если target и target_line оба nil, то target_thread по умолчанию будет текущим потоком, если задан блок.

trace.enabled?
#=> false

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

trace.enabled?
#=> false

Параметры target, target_line и target_thread используются для ограничения трассировки только определёнными объектами кода. target должен быть объектом кода, для которого RubyVM::InstructionSequence.of вернёт последовательность инструкций.

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

Примечание: Внутри блока enable нельзя получить доступ к обработчикам событий.

trace.enable { p tp.lineno }
#=> RuntimeError: access from outside
enabled? → true или false Показать исходный код
# File trace_point.rb, line 304
def enabled?
  Primitive.tracepoint_enabled_p
end

Текущее состояние трассировки

eval_script() Показать исходный код
# File trace_point.rb, line 407
def eval_script
  Primitive.tracepoint_attr_eval_script
end

Компилированный исходный код (String) в методах *eval в событии :script_compiled. Если загружено из файла, вернёт nil.

event() Показать исходный код
# File trace_point.rb, line 311
def event
  Primitive.tracepoint_attr_event
end

Тип события

См. События в TracePoint для получения дополнительной информации.

inspect → строка Показать исходный код
# File trace_point.rb, line 105
def inspect
  Primitive.tracepoint_inspect
end

Возвращает строку, содержащую удобочитаемое описание состояния TracePoint.

instruction_sequence() Показать исходный код
# File trace_point.rb, line 415
def instruction_sequence
  Primitive.tracepoint_attr_instruction_sequence
end

Компилированная последовательность инструкций, представленная экземпляром RubyVM::InstructionSequence в событии :script_compiled.

Обратите внимание, что этот метод специфичен для MRI.

lineno() Показать исходный код
# File trace_point.rb, line 316
def lineno
  Primitive.tracepoint_attr_lineno
end

Номер строки события

method_id() Показать исходный код
# File trace_point.rb, line 332
def method_id
  Primitive.tracepoint_attr_method_id
end

Возвращает имя метода по его определению.

parameters() Показать исходный код
# File trace_point.rb, line 327
def parameters
  Primitive.tracepoint_attr_parameters
end

Возвращает определения параметров метода или блока, к которому относится текущий обработчик. Формат аналогичен формату в Method#parameters

path() Показать исходный код
# File trace_point.rb, line 321
def path
  Primitive.tracepoint_attr_path
end

Путь к выполняемому файлу

raised_exception() Показать исходный код
# File trace_point.rb, line 401
def raised_exception
  Primitive.tracepoint_attr_raised_exception
end

Значение исключения, поднятого в событии :raise, или перехваченного в событии :rescue.

return_value() Показать исходный код
# File trace_point.rb, line 396
def return_value
  Primitive.tracepoint_attr_return_value
end

Возвращаемое значение из событий :return, :c_return и :b_return.

self() Показать исходный код
# File trace_point.rb, line 391
def self
  Primitive.tracepoint_attr_self
end

Возвращает объект трассировки во время события.

Аналогично, но возвращает правильный объект (получатель метода) для событий :c_call и :c_return:

trace.binding.eval('self')

Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API