класс 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)
Публичные методы класса
# 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, иначе он будет вызывать себя бесконечно).
# 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)
Доступ из других потоков также запрещён.
# File trace_point.rb, line 118 def self.stat Primitive.tracepoint_stat_s end
Возвращает внутреннюю информацию о TracePoint.
Содержимое возвращаемого значения зависит от реализации. Оно может изменяться в будущем.
Этот метод предназначен только для отладки TracePoint самого.
# 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
Общедоступные методы экземпляров
# File trace_point.rb, line 381 def binding Primitive.tracepoint_attr_binding end
Возвращает сгенерированный объект привязки из события.
Обратите внимание, что для событий :c_call и :c_return метод вернёт nil, так как у самих C-методов нет привязок.
# File trace_point.rb, line 337 def callee_id Primitive.tracepoint_attr_callee_id end
Возвращает имя вызываемого метода.
# 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
# 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
# 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
# File trace_point.rb, line 304 def enabled? Primitive.tracepoint_enabled_p end
Текущее состояние трассировки
# File trace_point.rb, line 407 def eval_script Primitive.tracepoint_attr_eval_script end
Компилированный исходный код (String) в методах *eval в событии :script_compiled. Если загружено из файла, вернёт nil.
# File trace_point.rb, line 311 def event Primitive.tracepoint_attr_event end
Тип события
См. События в TracePoint для получения дополнительной информации.
# File trace_point.rb, line 105 def inspect Primitive.tracepoint_inspect end
Возвращает строку, содержащую удобочитаемое описание состояния TracePoint.
# File trace_point.rb, line 415 def instruction_sequence Primitive.tracepoint_attr_instruction_sequence end
Компилированная последовательность инструкций, представленная экземпляром RubyVM::InstructionSequence в событии :script_compiled.
Обратите внимание, что этот метод специфичен для MRI.
# File trace_point.rb, line 316 def lineno Primitive.tracepoint_attr_lineno end
Номер строки события
# File trace_point.rb, line 332 def method_id Primitive.tracepoint_attr_method_id end
Возвращает имя метода по его определению.
# File trace_point.rb, line 327 def parameters Primitive.tracepoint_attr_parameters end
Возвращает определения параметров метода или блока, к которому относится текущий обработчик. Формат аналогичен формату в Method#parameters
# File trace_point.rb, line 321 def path Primitive.tracepoint_attr_path end
Путь к выполняемому файлу
# File trace_point.rb, line 401 def raised_exception Primitive.tracepoint_attr_raised_exception end
Значение исключения, поднятого в событии :raise, или перехваченного в событии :rescue.
# File trace_point.rb, line 396 def return_value Primitive.tracepoint_attr_return_value end
Возвращаемое значение из событий :return, :c_return и :b_return.
# 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.