Using trace and dbg in Erlang

I am trying to start using erlang: trace / 3 and the dbg module to track the behavior of a live production system without dropping the server.

Documentation opaque (to put it mildly), and there seems to be no useful tutorials on the Internet.

What I spent all day trying to do was capture what was happening in a particular function, trying to apply tracing to a module: a function using dbg: c and dbg: p, but without success at all ...

Does anyone have a brief explanation on how to use tracing in a live Erlang system?

+62
debugging erlang trace
Dec 23 '09 at 19:40
source share
4 answers

If you prefer a graphical tracer, try erlyberly . It allows you to choose the functions that you want to track (in all processes at the moment) and deals with the dbg API.

However, it does not protect against overload and is therefore not suitable for production systems.

enter image description here

+7
Dec 17 '14 at 22:12
source share

The main steps for tracing function calls are given in inanimate node:

> dbg:start(). % start dbg > dbg:tracer(). % start a simple tracer process > dbg:tp(Module, Function, Arity, []). % specify MFA you are interested in > dbg:p(all, c). % trace calls (c) of that MFA for all processes. ... trace here > dbg:stop_clear(). % stop tracer and clear effect of tp and p calls. 

You can track multiple functions at once. Add functions by calling tp for each function. If you want to track non-exported functions, you need to call tpl . To remove functions, call ctp or ctpl same way. Some common tp calls:

 > dbg:tpl(Module, '_', []). % all calls in Module > dbg:tpl(Module, Function, '_', []). % all calls to Module:Function with any arity. > dbg:tpl(Module, Function, Arity, []). % all calls to Module:Function/Arity. > dbg:tpl(M, F, A, [{'_', [], [{return_trace}]}]). % same as before, but also show return value. 

The final argument is the conformance specification. You can play with this using dbg:fun2ms .

You can select processes to track with p (). Elements are described in the erlang: trace section. Some challenges:

 > dbg:p(all, c). % trace calls to selected functions by all functions > dbg:p(new, c). % trace calls by processes spawned from now on > dbg:p(Pid, c). % trace calls by given process > dbg:p(Pid, [c, m]). % trace calls and messages of a given process 

I guess you will never need to call erlang:trace directly, since dbg does almost everything for you.

The golden rule for a live node is to generate only the amount of trace output into the shell, which allows you to enter dbg:stop_clear(). . :)

I often use a tracer that automatically stops after several events. For example:

 dbg:tracer(process, {fun (_,100) -> dbg:stop_clear(); (Msg, N) -> io:format("~p~n", [Msg]), N+1 end, 0 }). 

If you are looking for debugging on remote sites (or multiple sites), search for pan , eper , inviso or onviso .

+82
Dec 23 '09 at 19:58
source share

In living systems, we rarely monitor the shell. If the system is configured correctly, it already collects your Erlang logs that were printed in the shell. I do not need to emphasize why this is important for any living node ...

Let me dwell on the files in more detail:

You can track a file that will generate binary output, which can be converted and analyzed later. (for further analysis or an automated control system, etc.)

An example would be:

  • Tracking multiple packed files (12x50 MB). Please always check the available disk space before using such a large track!

     dbg:tracer(port,dbg:trace_port(file,{"/log/trace",wrap,atom_to_list(node()),50000000,12})). 

    dbg:p(all,[call,timestamp,return_to]).

    • Always test the node test before adding anything to the live node shell!
    • It is recommended that you test the node or node replica first to try the scripts.

This means that consider the basic sequence of trace commands:

<1> dbg:stop_clear().

  • Always start by clearing the trace ports and ensuring that the previous trace does not interfere with the current trace.

<2> dbg:tracer().

  • Start the tracing process.

<3> dbg:p(all,[call, timestamp]).

  • In this case, we track all processes and function calls.

<4> dbg:tp( ... ).

  • As seen from Zed's answer.

<5> dbg:tpl( ... ).

  • As seen from Zed's answer.

<42> dbg:stop_clear().

  • Again, to ensure that all traces were recorded on the output and to avoid further inconvenience.

You can:

  • add triggers by defining some fun () - s in the shell to stop tracing at a given time or event. Recursive pleasure () is the best you can achieve, but be very careful when using them.

  • apply a huge variety of pattern mappings to ensure that you are only tracing for a particular process with a special function call with a specific type of argument ...

I had a problem some time ago when we had to check the contents of the ETS table and when a certain record appeared we had to stop the trace for 2-3 minutes.

I also offer the Erlang Programming book, written by Francesco Cesarini. ( Erlang Programming @Amazon )

+18
May 13 '10 at 20:06
source share

The 'dbg' module is a fairly low-level material. There are two hacks that I use very often for tasks that I usually need.

  • Use the Erlang CLI / shell extension code at http://www.snookles.com/erlang/user_default.erl . It was originally written (as far as I know) by Serge Aleinikov and was useful "the way I add user-defined functions to the shell." compile the module and edit the ~ / .erlang file to indicate its path (see the comment at the top of the file).

  • Use the redbug utility contained in the EPER utility suite. It is very simple to use "dbg" to create millions of trace events in a few seconds. business therefore in a production environment can be disastrous. For development or production, redbug makes it almost impossible to kill a running system with trace overload.

+8
May 14 '10 at 1:44
source share



All Articles