Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Ruby 메서드를 감시하는 방법

Ruby에는 TracePoint를 사용하여 액세스할 수 있는 추적 시스템이 내장되어 있습니다. 수업. 추적할 수 있는 것 중 일부는 메서드 호출, 새 스레드 및 예외입니다.

왜 이것을 사용하시겠습니까?

특정 메소드의 실행을 추적하려는 경우에 유용할 수 있습니다. 호출되는 다른 메서드와 반환 값이 무엇인지 확인할 수 있습니다.

몇 가지 예를 살펴보겠습니다!

메소드 호출 추적

대부분의 경우 TracePoint가 필요합니다. 내장 메소드가 아닌 애플리케이션 코드(예:넣기, 크기 등)를 추적합니다.

call을 사용하여 이 작업을 수행할 수 있습니다. 이벤트.

:

def the_method; other_method; end
def other_method; end

def start_trace
  trace =
  TracePoint.new(:call) { |tp| p [tp.path, tp.lineno, tp.event, tp.method_id] }

  trace.enable
  yield
  trace.disable
end

start_trace { the_method }

파일 경로, 줄 번호, 이벤트 이름 및 메서드 이름을 인쇄합니다.

["test.rb", 1, :call, :the_method]
["test.rb", 2, :call, :other_method]

이벤트를 지정하지 않으면 Ruby는 모든 이벤트에 대해 블록을 호출하여 더 많은 출력을 생성합니다. 따라서 원하는 이벤트를 더 빨리 찾으려면 특정 이벤트에 집중하는 것이 좋습니다. 🙂

다음은 TracePoint의 표입니다. 이벤트:

이벤트 이름 설명
통화 신청 방법
c_call C 레벨 메소드(예:puts)
반환 메서드 반환(반환 값 및 호출 깊이 추적용)
b_call 통화 차단
b_return 블록 반환
증가 예외 발생
thread_begin 새 스레드
thread_end 스레드 종료

TracePoint + Graphviz

많은 메소드는 특히 프레임워크 코드에서 3개 이상의 메소드 호출을 수행하므로 Tracepoint의 출력 시각화하기 어려울 수 있습니다.

그래서 다음과 같은 시각적 호출 그래프를 만들 수 있는 보석을 만들었습니다.

require 'visual_call_graph'

VisualCallGraph.trace { "Your method call here..." }

이것은 call_graph.png를 생성합니다. 결과가 포함된 파일입니다.

Ruby 메서드를 감시하는 방법

이것은 정적 분석이 아니며 실제로 메서드를 호출합니다.

파일 경로 표시

이러한 메서드가 정의된 위치를 알고 싶으십니까?

걱정하지 마세요, 내가 당신을 덮었습니다! 각 메서드 호출에 대한 파일 경로를 표시하도록 활성화할 수 있는 옵션을 추가했습니다.

VisualCallGraph.trace(show_path: true) { Foo.aaa }

결과 :

Ruby 메서드를 감시하는 방법

대규모 호출 그래프를 보려면 몇 가지 Rails 메서드를 추적하기만 하면 됩니다 😉

반환 값

소개에서 나는 반환 값을 얻을 수도 있다고 언급했습니다...

이를 위해서는 return을 추적해야 합니다. 이벤트 및 return_value 사용 방법.

:

def the_method; "A" * 10; end

trace = TracePoint.new(:return) { |tp| puts "Return value for #{tp.method_id} is #{tp.return_value}." }

trace.enable
the_method
trace.disable

다음과 같이 인쇄됩니다.

Return value for the_method is AAAAAAAAAA.

이벤트 우선

누군가 reddit에서 foo를 호출할 때 "bar"라는 단어가 인쇄되지 않도록 하는 방법을 물었습니다. 다음 코드의 메서드:

class Thing
  def foo
    puts "foo"
    bar
  end

  def bar
    puts "bar"
  end
end

# your code here

t = Thing.new
t.foo

모듈을 추가하거나 $stdout을 리디렉션하는 것과 같이 이를 달성하는 방법에는 여러 가지가 있습니다. 또는 bar 재정의 방법.

<블록 인용>

창의력이 느껴진다면 이 게시물에 자신의 아이디어를 댓글로 달아주세요!

그러나 TracePoint를 사용했기 때문에 특히 흥미로운 답변 중 하나를 찾았습니다. 수업.

여기 있습니다 :

TracePoint.trace(:call) { |tp| exit if tp.method_id == :bar }
인 경우 종료

이 코드는 exit를 호출합니다. 메소드 bar일 때 프로그램을 종료하여 문자열이 인쇄되지 않도록 합니다.

아마도 실제 코드에서 사용하고 싶은 것은 아니지만 TracePoint에 대해 한 가지를 증명합니다. :이벤트가 발생하기 전에 트리거됩니다.

이와 관련하여 일종의 도구를 구축하려는 경우 염두에 두어야 할 사항 🙂

요약

이 게시물에서 TracePoint에 대해 배웠습니다. 메서드 호출이나 새 스레드와 같은 몇 가지 이벤트를 추적할 수 있는 클래스입니다. 이것은 디버깅 도구나 코드 탐색에 유용할 수 있습니다.

이 게시물을 공유하는 것을 잊지 마세요. 더 많은 사람들이 즐길 수 있도록 🙂