Black Bytes
Share this post!

How To Spy on Your Ruby Methods

Ruby has a built-in tracing system which you can access using the TracePoint class. Some of the things you can trace are method calls, new threads & exceptions.

Why would you want to use this?

Well, it could be useful if you want to trace the execution of a certain method. You will be able to see what other methods are being called & what are the return values.

Let’s see a few examples!

Tracing Method Calls

Most of the time you will want TracePoint to trace application code & not built-in methods (like puts, size, etc).

You can do this using the call event.

Example:

This prints the file path, the line number, the event name & the method name.

If you don’t specify any events Ruby will call your block for all of them, resulting in more output. So I would recommend that you focus on specific events to find what you want faster 🙂

Here’s is a table of TracePoint events:

Event name Description
call Application methods
c_call C-level methods (like puts)
return Method return (for tracing return values & call depth)
b_call Block call
b_return Block return
raise Exception raised
thread_begin New thread
thread_end Thread ending

TracePoint + Graphviz

Many methods will make more than just 3 methods calls, especially in framework code, so the output from Tracepoint can be hard to visualize.

So I made a gem that lets you create a visual call graph like this:

This generates a call_graph.png file with the results.

ruby call graph

Keep in mind that this is not static analysis, this will actually call the method!

Showing File Paths

Would you like to know where these methods are defined?

Don’t worry, I got you covered! I added an option you can enable to show the file path for each method call.

Which results in:

visual call graph

If you want to see some massive call graphs you just have to trace some Rails methods 😉

Return Values

In the intro I mentioned that you can also get return values. For this you will need to trace the return event and use the return_value method.

Example:

This will print:

Events First

Someone asked on reddit how it’s possible to avoid having the word “bar” printed when calling the foo method in the following code:

There are many ways to achieve this, like prepending a module, redirecting $stdout or redefining the bar method.

If you are feeling creative, comment on this post with your own idea!

But I found one of the answers particularly interesting because it used the TracePoint class.

Here it is:

This code will call exit when the method bar is called, which prevents the string from being printed by ending the program.

Probably not something you want to use in real code, but it proves one thing about TracePoint: Events are triggered before they happen.

Something to keep in mind if you are going to build some sort of tool around this 🙂

Summary

In this post you learned about the TracePoint class, which allows you to trace a few events like methods calls or new threads. This can be useful as a debugging tool or for code exploration.

Remember to share this post so more people can enjoy it 🙂

Leave a Comment:

7 comments
ttwo32 says last week

This is a useful way . I sometimes want to trace the execution without pry.
Is your gem https://github.com/matugm/visual-call-graph ?

Reply
    Jesus Castello says last week

    Yes, that’s my gem 🙂

    Reply
      ttwo32 says last week

      Thanks!
      I will check your gem 🙂

      Reply
Tokara says 6 days ago

Heads up to those trying the visual_call_graph gem. It requires graphviz to be installed, which can be downloaded at:
http://www.graphviz.org

Thanks for the wonderful gem!

Reply
    Jesus Castello says 6 days ago

    Thanks for reading 🙂

    Reply
Arun says 5 days ago

nice one and useful… Thanks

Reply
    Jesus Castello says 5 days ago

    Thank you! I’m glad you found it useful 🙂

    Reply
Add Your Reply