How to use the dbg tracer in Elixir

I’m trying to use the dbg tracer from Erlang in Elixir. At the moment I have the following line:

:dbg.tracer(process, fn (msg, _) -> IO.puts("DEBUG: #{msg}") end)

This raises the error:

** (CompileError) iex:1: undefined function process/0
    (stdlib 3.16.1) lists.erl:1358: :lists.mapfoldl/3

Any help with this would be appreciated. I’m myself pretty new to Elixir and Erlang, so it’s very possible it’s something very simple that I’m doing wrong.

Kind regards!

The first argument of :dbg.tracer/2 is type which is one of the atoms :port | :process | :module.
You probably got that example mixed from some source in Erlang. process in Erlang is an atom. So the equivalent in elixir would be :process

:dbg.tracer(:process, fn (msg, _) -> IO.puts("DEBUG: #{msg}") end)
2 Likes

I usually suggest GitHub - redink/extrace: Elixir wrapper for Recon Trace., which translates quite well from and to erlang.

2 Likes

I’ve read the page you linked but this seems to only be able to trace function calls? In my case I am trying to trace message sends and receives.

This works, I was indeed confused by the documentation (which is for Erlang). It raises another error though:

iex(1)> :dbg.tracer(:process, fn (msg, _) -> IO.puts("DEBUG:  #{msg}") end) 
** (FunctionClauseError) no function clause matching in :dbg.tracer/2    

    The following arguments were given to :dbg.tracer/2:

        # 1
        :process

        # 2
        #Function<43.65746770/2 in :erl_eval.expr/5>

    (runtime_tools 1.17) dbg.erl:308: :dbg.tracer/2

It seems to not find the function. Note, this function does exist in Erlang (as can be seen in the documentation I linked) and :dbg.tracer() works as well.

From looking at the docs it appears as though that function does not take a two-arity function as its second argument. It should either be a zero-arity function, or a tuple with a two-arity function and the initial data for that function. This is the Erlang type syntax which specifies this:

Data = PortGenerator | HandlerSpec | ModuleSpec
PortGenerator = fun() (no arguments)
Error = term()
HandlerSpec = {HandlerFun, InitialData}
HandlerFun = fun() (two arguments)
ModuleSpec = fun() (no arguments) |{TracerModule, TracerState}
TracerModule = atom()
InitialData = TracerState = term()
3 Likes

This seems to have fixed it! I simply added a dummy initial value (since I don’t need one yet). Thanks a lot!