Ruby có một hệ thống theo dõi tích hợp mà bạn có thể truy cập bằng cách sử dụng TracePoint
lớp. Một số thứ bạn có thể theo dõi là lời gọi phương thức, chuỗi mới và ngoại lệ.
Tại sao bạn muốn sử dụng cái này?
Chà, nó có thể hữu ích nếu bạn muốn theo dõi việc thực thi một phương thức nào đó. Bạn sẽ có thể thấy những phương thức khác đang được gọi và giá trị trả về là gì.
Hãy xem một vài ví dụ!
Cuộc gọi phương pháp theo dõi
Hầu hết thời gian bạn sẽ muốn TracePoint
để theo dõi mã ứng dụng và không phải các phương thức tích hợp sẵn (như đặt, kích thước, v.v.).
Bạn có thể thực hiện việc này bằng cách sử dụng call
sự kiện.
Ví dụ :
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 }
Thao tác này in ra đường dẫn tệp, số dòng, tên sự kiện và tên phương thức.
["test.rb", 1, :call, :the_method] ["test.rb", 2, :call, :other_method]
Nếu bạn không chỉ định bất kỳ sự kiện nào, Ruby sẽ gọi khối của bạn cho tất cả chúng, dẫn đến kết quả đầu ra nhiều hơn. Vì vậy, tôi khuyên bạn nên tập trung vào các sự kiện cụ thể để tìm thấy những gì bạn muốn nhanh hơn 🙂
Đây là bảng của TracePoint
sự kiện:
Tên sự kiện | Mô tả |
---|---|
gọi | Phương pháp ứng dụng |
c_call | Phương thức cấp C (như đặt) |
quay lại | Phương thức trả về (để theo dõi giá trị trả về và độ sâu lệnh gọi) |
b_call | Chặn cuộc gọi |
b_return | Chặn trả lại |
tăng | Nâng cao ngoại lệ |
thread_begin | Chủ đề mới |
thread_end | Kết thúc chuỗi |
TracePoint + Graphviz
Nhiều phương thức sẽ thực hiện nhiều hơn chỉ 3 cuộc gọi phương thức, đặc biệt là trong mã khung, vì vậy kết quả đầu ra từ Tracepoint
có thể khó hình dung.
Vì vậy, tôi đã tạo một viên đá quý cho phép bạn tạo một biểu đồ cuộc gọi trực quan như sau:
require 'visual_call_graph' VisualCallGraph.trace { "Your method call here..." }
Điều này tạo ra một call_graph.png
gửi kết quả.
Hãy nhớ rằng đây không phải là phân tích tĩnh, đây thực sự sẽ gọi phương thức!
Hiển thị Đường dẫn Tệp
Bạn có muốn biết các phương pháp này được định nghĩa ở đâu không?
Đừng lo, tôi đã giúp bạn! Tôi đã thêm một tùy chọn mà bạn có thể bật để hiển thị đường dẫn tệp cho mỗi lệnh gọi phương thức.
VisualCallGraph.trace(show_path: true) { Foo.aaa }
Kết quả nào dẫn đến :
Nếu bạn muốn xem một số đồ thị cuộc gọi lớn, bạn chỉ cần theo dõi một số phương thức Rails 😉
Giá trị trả lại
Trong phần giới thiệu, tôi đã đề cập rằng bạn cũng có thể nhận các giá trị trả về…
Đối với điều này, bạn sẽ cần theo dõi return
sự kiện và sử dụng return_value
phương pháp.
Ví dụ :
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
Điều này sẽ in:
Return value for the_method is AAAAAAAAAA.
Sự kiện đầu tiên
Có người đã hỏi trên reddit làm cách nào để tránh in từ “bar” khi gọi foo
trong đoạn mã sau:
class Thing def foo puts "foo" bar end def bar puts "bar" end end # your code here t = Thing.new t.foo
Có nhiều cách để đạt được điều này, chẳng hạn như thêm một mô-đun, chuyển hướng $stdout
hoặc xác định lại bar
phương pháp.
Nếu bạn cảm thấy sáng tạo, hãy bình luận về bài đăng này với ý tưởng của riêng bạn!
Nhưng tôi thấy một trong những câu trả lời đặc biệt thú vị vì nó sử dụng TracePoint
lớp học.
Đây rồi :
TracePoint.trace(:call) { |tp| exit if tp.method_id == :bar }
Mã này sẽ gọi exit
khi phương thức bar
được gọi, điều này ngăn không cho chuỗi được in khi kết thúc chương trình.
Có thể không phải là thứ bạn muốn sử dụng trong mã thực, nhưng nó chứng minh một điều về TracePoint
:Các sự kiện được kích hoạt trước khi chúng xảy ra.
Một điều cần lưu ý nếu bạn định xây dựng một số loại công cụ xung quanh vấn đề này 🙂
Tóm tắt
Trong bài đăng này, bạn đã học về TracePoint
lớp, cho phép bạn theo dõi một vài sự kiện như các cuộc gọi phương thức hoặc các luồng mới. Điều này có thể hữu ích như một công cụ gỡ lỗi hoặc để khám phá mã.
Hãy nhớ chia sẻ bài đăng này để nhiều người có thể thưởng thức nó 🙂