класс 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.attr! :use_block Primitive.tracepoint_allow_reentry end
В общем случае, пока выполняется обратный вызов TracePoint, другие зарегистрированные обратные вызовы не вызываются, чтобы избежать путаницы при повторном вызове. Этот метод разрешает повторный вызов внутри данного блока. Используйте этот метод осторожно, чтобы избежать бесконечного вызова обратных вызовов.
Если этот метод вызывается, когда повторный вызов уже разрешен, он вызывает исключение RuntimeError.
Пример:
# Without reentry
# ---------------
line_handler = TracePoint.new(:line) do |tp|
next if tp.path != __FILE__ # Only works 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 the :line
# handler, all other handlers are ignored.
# With reentry
# ------------
line_handler = TracePoint.new(:line) do |tp|
next if tp.path != __FILE__ # Only works in this file
next if (__LINE__..__LINE__+3).cover?(tp.lineno) # Prevent infinite calls
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 will print "Class handler" twice: inside the allow_reentry block in the :line
# handler, other handlers are enabled.
Обратите внимание, что пример демонстрирует основной эффект метода, но его практическое применение — для отладки библиотек, которые иногда требуют, чтобы другие библиотечные хуки не затрагивались отладчиком, находящимся внутри обработки точки отслеживания. В этом случае необходимо принять меры против бесконечной рекурсии (обратите внимание, что нам потребовалось отфильтровать вызовы самих себя из обработчика :line, иначе бы это привело к бесконечному вызову самого себя).
Исходный код
# File trace_point.rb, line 94 def self.new(*events) Primitive.attr! :use_block Primitive.tracepoint_new_s(events) end
Возвращает новый объект TracePoint, по умолчанию не активированный.
Для активации объекта 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 117 def self.stat Primitive.tracepoint_stat_s end
Возвращает внутреннюю информацию о TracePoint.
Содержимое возвращаемого значения зависит от реализации и может изменяться в будущем.
Этот метод предназначен только для отладки самого TracePoint.
Исходный код
# File trace_point.rb, line 132 def self.trace(*events) Primitive.attr! :use_block 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 возвращает единственный класс.
Шестой параметр блока 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 295 def disable Primitive.attr! :use_block 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 259 def enable(target: nil, target_line: nil, target_thread: :default) Primitive.attr! :use_block 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 104 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.
Обратите внимание, что этот метод специфичен для CRuby.
Исходный код
# 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–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.