класс TracePoint
Класс документа: 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 -
выброс исключения
-
: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 199 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 97 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 119 def self.stat Primitive.tracepoint_stat_s end
Возвращает внутреннюю информацию о TracePoint.
Содержание возвращаемого значения зависит от реализации. Оно может быть изменено в будущем.
Этот метод предназначен только для отладки TracePoint само по себе.
# File trace_point.rb, line 134 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 383 def binding Primitive.tracepoint_attr_binding end
Возвращает сгенерированный объект привязки из события.
Обратите внимание, что для событий c_call и c_return возвращаемая привязка — это привязка ближайшего Ruby-метода, вызывающего C-метод, так как у самих C-методов нет привязок.
# File trace_point.rb, line 338 def callee_id Primitive.tracepoint_attr_callee_id end
Возвращает имя вызываемого метода.
# File trace_point.rb, line 374 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 297 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 261 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 305 def enabled? Primitive.tracepoint_enabled_p end
Текущий статус отслеживания
# File trace_point.rb, line 409 def eval_script Primitive.tracepoint_attr_eval_script end
Скомпилированный исходный код (String) для методов *eval в событии :script_compiled. Если загружено из файла, вернёт nil.
# File trace_point.rb, line 312 def event Primitive.tracepoint_attr_event end
Тип события
См. События в TracePoint для получения дополнительной информации.
# File trace_point.rb, line 106 def inspect Primitive.tracepoint_inspect end
Возвращает строку с удобочитаемым статусом TracePoint.
# File trace_point.rb, line 417 def instruction_sequence Primitive.tracepoint_attr_instruction_sequence end
Скомпилированная последовательность инструкций, представленная экземпляром RubyVM::InstructionSequence в событии :script_compiled.
Обратите внимание, что этот метод специфичен для MRI.
# File trace_point.rb, line 317 def lineno Primitive.tracepoint_attr_lineno end
Номер строки события
# File trace_point.rb, line 333 def method_id Primitive.tracepoint_attr_method_id end
Возвращает имя метода в его определении.
# File trace_point.rb, line 328 def parameters Primitive.tracepoint_attr_parameters end
Возвращает определение параметров метода или блока, к которому относится текущий обработчик. Формат аналогичен формату Method#parameters.
# File trace_point.rb, line 322 def path Primitive.tracepoint_attr_path end
Путь к выполняемому файлу.
# File trace_point.rb, line 403 def raised_exception Primitive.tracepoint_attr_raised_exception end
Значение исключения, выброшенного в событии :raise.
# File trace_point.rb, line 398 def return_value Primitive.tracepoint_attr_return_value end
Возвращаемое значение в событиях :return, c_return, и b_return.
# File trace_point.rb, line 393 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.