Techniques to track function calls

I am wondering what different options are available to track function calls in an Elixir app. Here’s what I have so far:

Trace via :dbg module or :recon_trace

This approach is nice because you don’t need to change existing code to use it. It just hooks into any module/function that you want.

The downside is that you can only have a single tracer per process. I thought that I could overcome this by starting the tracer inside of a different process, but it seems to not have helped. There may be some nuance here that I’m missing.

Write a __using__ macro that hooks into before_compile and overrides a function

This one feels very easy to understand, but would require use Something in every module that wants to implement it. If I’m trying to do a code-level cross-cutting concern, then I don’t want to add annotations to every module.

I also like that the args/return are available in the same block of code. I can whip something together with tracing, but it won’t be exact because the call/return traces are separate.

Other Options?

Any other approaches on this problem? Links to code are always appreciated.

2 Likes

Besides :dbg and :recon_trace, I have also used Rexbug for tracing (it uses :redbug under the hoods). It’s fairly simple and I got there because it gives the option to drop the stacktrace of the calls aside from just the return value (which I couldn’t find in :recon and haven’t explored :dbg for that matter). I’m not sure about how it attaches tracers to processes, if it allows for multiple, but it’s another nice tool to play with. :slight_smile:

I gave a talk in the last Code BEAM Brazil where I went over tracing and memory allocation diagnostics tools, here are the slides (don’t know if it helps, but either way): Diagnosing bugs in production with Elixir - Speaker Deck

3 Likes