View Source dbg (runtime_tools v2.1)
The Text Based Trace Facility
This module implements a text based interface to the
trace:process/4
, trace:port/4
, and trace:function/4
BIFs,
simplifying tracing of functions, processes, ports, and messages.
To quickly get started on tracing function calls you can use the following code in the Erlang shell:
1> dbg:tracer(). % Start the default trace message receiver
{ok,<0.90.0>}
2> dbg:p(all, c). % Set upp call tracing on all processes
{ok,[{matched,nonode@nohost,49}]}
3> dbg:tp(lists, seq, cx). % Set up call and exception tracing on lists:seq/2,3
{ok,[{matched,nonode@nohost,2},{saved,cx}]}
4> lists:seq(1, 10).
(<0.88.0>) call lists:seq(1,10) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
[1,2,3,4,5,6,7,8,9,10]
(<0.88.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
The utilities are also suitable to use in system testing on large systems, where other tools have too severe impact on the system performance. Some primitive support for sequential tracing is also included; see the advanced topics section.
Simple tracing from the shell with no prior set up
To trace a call to a function with minimal fuss, call dbg:c(Module, Name, Arguments)
. dbg:c/3
starts a temporary trace
receiver, enables all trace flags, and calls the designated function
from a temporary process. For example, here is how to trace a call
to application:which_applications/0
:
1> dbg:c(application, which_applications, []).
(<0.92.0>) <0.45.0> ! {'$gen_call',{<0.92.0>,
[alias|
#Ref<0.0.11779.270031856.1478295555.230456>]},
which_applications} (Timestamp: {1710,
847802,
479222})
(<0.92.0>) out {gen,do_call,4} (Timestamp: {1710,847802,479231})
(<0.92.0>) in {gen,do_call,4} (Timestamp: {1710,847802,479271})
(<0.92.0>) << {[alias|#Ref<0.0.11779.270031856.1478295555.230456>],
[{stdlib,"ERTS CXC 138 10","5.2.1"},
{kernel,"ERTS CXC 138 10","9.2.2"}]} (Timestamp: {1710,
847802,
479274})
[{stdlib,"ERTS CXC 138 10","5.2.1"},
{kernel,"ERTS CXC 138 10","9.2.2"}]
Four trace events are generated:
- A send event (
!
) for the sending of a request from the current process to theapplication_controller
process. - A schedule-out event (
out
) when the current process schedules out while waiting in areceive
for the reply to arrive. - A schedule-in event (
in
) when the current process is scheduled in when reply has arrived. - A
receive
event (<<
) when the current process retrieves the reply from theapplication_controller
process.
The dbg:c/4
function has a fourth argument for specifying the trace flags.
Here is how to only show message sending and receiving:
2> dbg:c(application, which_applications, [], m).
(<0.96.0>) <0.45.0> ! {'$gen_call',{<0.96.0>,
[alias|
#Ref<0.0.12291.270031856.1478295555.230496>]},
which_applications}
(<0.96.0>) << {[alias|#Ref<0.0.12291.270031856.1478295555.230496>],
[{stdlib,"ERTS CXC 138 10","5.2.1"},
{kernel,"ERTS CXC 138 10","9.2.2"}]}
[{stdlib,"ERTS CXC 138 10","5.2.1"},
{kernel,"ERTS CXC 138 10","9.2.2"}]
Tracing from the shell
Another way of tracing from the shell is to explicitly start a tracer and set the trace flags of your choice on the processes you want to trace. For example, here is how to trace messages and process events:
1> Pid = spawn(fun() -> receive {From,Msg} -> From ! Msg end end).
<0.90.0>
2> dbg:tracer().
{ok,<0.92.0>}
3> dbg:p(Pid, [m,procs]).
{ok,[{matched,nonode@nohost,1}]}
4> Pid ! {self(),hello}.
(<0.90.0>) << {<0.88.0>,hello}
{<0.88.0>,hello}
(<0.90.0>) <0.88.0> ! hello
(<0.90.0>) exit normal
5> flush().
Shell got hello
ok
In order to trace functions call, in addition to enabling the call
trace flag
for the process, it is also necessary to set a trace pattern for the functions
to trace.
Example:
1> dbg:tracer().
{ok,<0.90.0>}
2> dbg:p(all, call).
{ok,[{matched,nonode@nohost,49}]}
3> dbg:tp(lists, last, 1, []).
{ok,[{matched,nonode@nohost,1}]}
4> lists:last([a,b,c,d,e]).
(<0.88.0>) call lists:last([a,b,c,d,e])
e
5> dbg:tp(lists, last, 1, [{'_',[],[{return_trace}]}]).
{ok,[{matched,nonode@nohost,1},{saved,1}]}
6> lists:last([a,b,c,d,e]).
(<0.88.0>) call lists:last([a,b,c,d,e])
(<0.88.0>) returned from lists:last/1 -> e
e
Advanced topics - combining with seq_trace
The dbg
module is primarily targeted towards tracing through the
trace:process/4
function. It is sometimes desired to trace messages in a more
delicate way, which can be done with the help of the seq_trace
module.
seq_trace
implements sequential tracing (known in the AXE10 world, and
sometimes called "forlopp tracing"). dbg
can interpret messages generated from
seq_trace
and the same tracer function for both types of tracing can be used.
The seq_trace
messages can also be sent to a trace port for further analysis.
As a match specification can turn on sequential tracing, the combination of
dbg
and seq_trace
can be powerful. This brief example shows a session
where sequential tracing is used to trace the dbg
module and the trace itself:
1> dbg:tracer().
{ok,<0.30.0>}
2> {ok, Tracer} = dbg:get_tracer().
{ok,<0.31.0>}
3> seq_trace:set_system_tracer(Tracer).
false
4> dbg:tp(dbg, get_tracer, 0, [{[],[],[{set_seq_token, send, true}]}]).
{ok,[{matched,nonode@nohost,1},{saved,1}]}
5> dbg:p(all,call).
{ok,[{matched,nonode@nohost,22}]}
6> dbg:get_tracer(), seq_trace:set_token([]).
(<0.25.0>) call dbg:get_tracer()
SeqTrace [0]: (<0.25.0>) <0.30.0> ! {<0.25.0>,get_tracer} [Serial: {2,4}]
SeqTrace [0]: (<0.30.0>) <0.25.0> ! {dbg,{ok,<0.31.0>}} [Serial: {4,5}]
{1,0,5,<0.30.0>,4}
This session sets the system_tracer to the same process as the
ordinary tracer process (i. e. <0.31.0>) and sets the trace pattern
for the function dbg:get_tracer
to one that has the action of
setting a sequential token. When the function is called by a traced
process (all processes are traced in this case), the process gets
"contaminated" by the token and seq_trace
messages are sent both for
the server request and the response. The seq_trace:set_token([])
after the call clears the seq_trace
token, which is why no messages
are sent when the answer propagates via the shell to the console
port. Otherwise the output would been more noisy.
Note of caution
When tracing function calls on a group leader process (an I/O process), there is
risk of causing a deadlock. This will happen if a group leader process generates
a trace message and the tracer process, by calling the trace handler function,
sends an I/O request to the same group leader. The problem can only occur if the
trace handler prints to the tty using an io
function such as
format/2
. Note that when dbg:p(all, call)
is called, IO
processes are also traced. Here is an example:
%% Using a default line editing shell
1> dbg:tracer(process, {fun(Msg,_) -> io:format("~p~n", [Msg]), 0 end, 0}).
{ok,<0.37.0>}
2> dbg:p(all, [call]).
{ok,[{matched,nonode@nohost,25}]}
3> dbg:tp(mymod,[{'_',[],[]}]).
{ok,[{matched,nonode@nohost,0},{saved,1}]}
4> mymod: % TAB pressed here
%% -- Deadlock --
Here is another example:
%% Using a shell without line editing (oldshell)
1> dbg:tracer(process).
{ok,<0.31.0>}
2> dbg:p(all, [call]).
{ok,[{matched,nonode@nohost,25}]}
3> dbg:tp(lists,[{'_',[],[]}]).
{ok,[{matched,nonode@nohost,0},{saved,1}]}
% -- Deadlock --
The reason we get a deadlock in the first example is because when TAB is pressed
to expand the function name, the group leader (which handles character input)
calls mymod:module_info()
. This generates a trace message which, in turn,
causes the tracer process to send an IO request to the group leader (by calling
io:format/2
). We end up in a deadlock.
In the second example we use the default trace handler function. This
handler prints to the tty by sending IO requests to the user
process. When Erlang is started in the oldshell mode, the shell
process will have user
as its group leader and so will the tracer
process in this example. Since user
calls functions in lists
we
end up in a deadlock as soon as the first IO request is sent.
Here are a few suggestions for avoiding deadlock:
- Do not trace the group leader of the tracer process. If tracing has been
switched on for all processes, call
dbg:p(TracerGLPid, clear)
to stop tracing the group leader (TracerGLPid
).process_info(TracerPid, group_leader)
tells you which process this is (TracerPid
is returned fromdbg:get_tracer/0
). - Do not trace the
user
process if using the default trace handler function. - In your own trace handler function, call
erlang:display/1
instead of anio
function or, ifuser
is not used as group leader, print touser
instead of the default group leader. Example:io:format(user, Str, Args)
.
Summary
Functions
Equivalent to c(Mod, Fun, Args, all)
.
Evaluates the expression apply(Mod, Fun, Args)
with the
trace flags in Flags
set.
Clears a node from the list of traced nodes.
Equivalent to ctp({'_', '_', '_'})
.
Disables call tracing for one or more functions specified by ModuleOrMFA
.
Equivalent to ctp({Module, Function, '_'})
.
Equivalent to ctp({Module, Function, Arity})
.
Clears match specifications for the specified trace event (send
or
'receive'
), reverting to the default of tracing all triggered events.
Equivalent to ctpg({'_', '_', '_'})
.
Disables global call tracing for one or more functions specified by ModuleOrMFA
.
Equivalent to ctpg({Module, Function, '_'})
.
Equivalent to ctpg({Module, Function, Arity})
.
Equivalent to ctpl({'_', '_', '_'})
.
Disables local call tracing for one or more functions specified by ModuleOrMFA
.
Equivalent to ctpl({Module, Function, '_'})
.
Equivalent to ctpl({Module, Function, Arity})
.
Equivalent to flush_trace_port(node())
.
Equivalent to trace_port_control(Nodename, flush)
.
Pseudo function that by means of a parse transform translates the literal fun typed as parameter in the function call to a match specification.
Equivalent to get_tracer(node())
.
Returns the process, port, or tracer module to which all trace messages are sent.
Gives a list of items for brief online help.
Gives a brief help text for functions in the dbg
module.
Displays information about all traced processes and ports.
Shows the list of traced nodes on the console.
Lists all match specifications previously used in the session.
Adds a remote node (Nodename
) to the list of nodes where tracing is
performed.
Equivalent to p(Item, [m])
.
Traces Item
in accordance to the value specified by Flags
.
Runs dbg
commands using the provides session, or
creates a session for the duration of the call if a session name
is provided.
Create a new dbg
session with the given Name
.
Destroys a dbg session/0
.
Stops the dbg
server, clears all trace flags for all processes, clears all
trace patterns for all functions, clears trace patterns for send/receive, shuts
down all trace clients, and closes all trace ports.
Shuts down a previously started trace client.
Enables call trace for one or more exported functions specified by ModuleOrMFA
.
Associates a match specification with trace event send
or
'receive'
.
Enables call trace for one or more functions specified by ModuleOrMFA
.
Starts a trace client that reads the output created by a trace port
driver (see trace_port/2
) and handles it in mostly the same way as a
tracer process created by the tracer/0
function.
This function works exactly as trace_client/2
, but allows you to write your
own handler function.
Creates a trace-port-generating fun that is suitable as the
second argument to tracer/2
.
This function is used to do a control operation on the active trace port driver
on the given node (Nodename
).
Starts a server on the local node that will be the recipient of all trace messages.
Starts a tracer server with additional parameters on the local node.
This function is equivalent to tracer/2
, but acts on the given node.
Types
-type built_in_alias() :: x | c | cx.
-type match_desc() :: [match_info()].
-type match_spec() :: [{match_pattern(), [_], [_]}].
-opaque session()
A dbg
session that can be used by session/2
to
create isolated debugging sessions.
-type tp_arity() :: arity() | '_'.
-type tp_function() :: atom() | '_'.
-type tp_id() :: pos_integer().
-type tp_match_spec() :: tp_id() | built_in_alias() | [] | match_spec().
-type tp_module() :: module() | '_'.
-type trace_wrap_file_size() :: non_neg_integer() | {time, WrapTime :: pos_integer()}.
-type trace_wrap_files_spec() :: {file:name_all(), wrap, Suffix :: string()} | {file:name_all(), wrap, Suffix :: string(), WrapSize :: trace_wrap_file_size()} | {file:name_all(), wrap, Suffix :: string(), WrapSize :: trace_wrap_file_size(), WrapCnt :: pos_integer()}.
Functions
Equivalent to c(Mod, Fun, Args, all)
.
Evaluates the expression apply(Mod, Fun, Args)
with the
trace flags in Flags
set.
c
stands for call.
This is a convenient way to trace processes from the Erlang shell.
-spec cn(Nodename) -> ok when Nodename :: node().
Clears a node from the list of traced nodes.
cn
stands for clear node.
Subsequent calls to tp/2
and p/2
will not consider that node, but tracing
already activated on the node will continue to be in effect.
Returns ok
. This call cannot fail.
-spec ctp() -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctp({'_', '_', '_'})
.
-spec ctp(Module | {Module, Function, Arity}) -> {ok, MatchDesc :: match_desc()} | {error, term()} when Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity().
Disables call tracing for one or more functions specified by ModuleOrMFA
.
If ModuleOrMFA
is an atom (a module name), this function call is
equivalent to ctp({ModuleOrMFA, '_', '_'})
.
Otherwise, ModuleOrMFA
should be {Module, Function, Arity}
.
ctp
stands for clear trace pattern.
The semantics of ModuleOrMFA
is the same as for the corresponding function
specification in tp/2
or tpl/2
. Both local and global call trace
is disabled.
The return value reflects how many functions that matched, and is constructed as
described in tp/2
, except that no {saved, N}
tuple is returned.
-spec ctp(Module :: tp_module(), Function :: tp_function()) -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctp({Module, Function, '_'})
.
-spec ctp(Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity()) -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctp({Module, Function, Arity})
.
-spec ctpe(Event) -> {ok, MatchDesc} | {error, term()} when Event :: send | 'receive', MatchDesc :: [MatchNum], MatchNum :: {matched, node(), 1} | {matched, node(), 0, RPCError :: term()}.
Clears match specifications for the specified trace event (send
or
'receive'
), reverting to the default of tracing all triggered events.
ctpe
stands for clear trace pattern event.
-spec ctpg() -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctpg({'_', '_', '_'})
.
-spec ctpg(Module | {Module, Function :: tp_function(), Arity :: tp_arity()}) -> {ok, MatchDesc :: term()} | {error, term()} when Module :: tp_module().
Disables global call tracing for one or more functions specified by ModuleOrMFA
.
If ModuleOrMFA
is an atom (a module name), this function call is
equivalent to ctpg({ModuleOrMFA, '_', '_'})
.
Otherwise, ModuleOrMFA
should be {Module, Function, Arity}
.
ctpg
stands for clear trace pattern global.
This function works as ctp/1
, but only disables tracing set up with
tp/2
(not with tpl/2
).
-spec ctpg(Module :: tp_module(), Function :: tp_function()) -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctpg({Module, Function, '_'})
.
-spec ctpg(Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity()) -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctpg({Module, Function, Arity})
.
-spec ctpl() -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctpl({'_', '_', '_'})
.
-spec ctpl(Module | {Module, Function :: tp_function(), Arity :: tp_arity()}) -> {ok, MatchDesc :: term()} | {error, term()} when Module :: tp_module().
Disables local call tracing for one or more functions specified by ModuleOrMFA
.
If ModuleOrMFA
is an atom (a module name), this function call is
equivalent to ctpl({ModuleOrMFA, '_', '_'})
.
Otherwise, ModuleOrMFA
should be {Module, Function, Arity}
.
ctpl
stands for clear trace pattern local.
This function works as ctp/1
, but only disables tracing set up with
tpl/2
(not with tp/2
).
-spec ctpl(Module :: tp_module(), Function :: tp_function()) -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctpl({Module, Function, '_'})
.
-spec ctpl(Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity()) -> {ok, MatchDesc :: match_desc()} | {error, term()}.
Equivalent to ctpl({Module, Function, Arity})
.
-spec dtp() -> ok.
Forgets all match specifications saved during calls to tp/2
.
dtp
stands for delete trace patterns.
Removing all saved match specifications is useful before restoring
other match specifications from a file with rtp/1
. Use dtp/1
to
delete specific saved match specifications.
-spec dtp(N) -> ok when N :: tp_id().
Forgets a specific match specification saved during calls to tp/2
.
dtp
stands for delete trace pattern.
-spec flush_trace_port() -> term().
Equivalent to flush_trace_port(node())
.
Equivalent to trace_port_control(Nodename, flush)
.
-spec fun2ms(LiteralFun) -> MatchSpec when LiteralFun :: fun((term()) -> term()), MatchSpec :: match_spec().
Pseudo function that by means of a parse transform translates the literal fun typed as parameter in the function call to a match specification.
The meaning of "literal" is that the fun needs to textually be written
as the argument of the function call; it cannot be held in a variable
which in turn is passed to the function. Furthermore, the parse
transform module ms_transform
must be enabled. The easiest way to
enable it is by adding the following line to the source file:
-include_lib("stdlib/include/ms_transform.hrl").
Failing to include ms_transform.hrl
in the source will result in a runtime
error, not a compile-time error.
This function can also be invoked directly from the Erlang shell, as shown in the examples that follow.
The head of the fun must be a single pattern that matches a list. That pattern will be used to match the arguments for the call:
Examples:
1> dbg:fun2ms(fun([_,_]) -> true end).
[{['_','_'],[],[true]}]
2> dbg:fun2ms(fun(Args) when length(Args) > 6 -> true end).
[{'$1',[{'>',{length,'$1'},6}],[true]}]
The first match specification matches when a function having two arguments is called. The second matches when a function with more than 6 arguments is called.
Examples:
1> dbg:fun2ms(fun(42) -> true end).
Error: dbg:fun2ms requires fun with single variable or list parameter
{error,transform_error}
2> dbg:fun2ms(fun([<<H,T/binary>>]) -> true end).
Error: fun head contains bit syntax matching of variable 'H', which cannot be translated into match_spec
{error,transform_error}
The preceding two examples show what happens when a fun cannot be translated into a match specification. In the first example, the fun head connot possibly match a list. In the second example, an attempt is made to take apart a binary using the bit syntax, which is currently not supported in match specifications.
However, note that literal binaries can be matched:
1> dbg:fun2ms(fun([<<"abc">>]) -> true end).
[{[<<"abc">>],[],[true]}]
Match specifications support a large subset of the guard expressions supported by Erlang, but not all. For example, updating a map is currently not supported:
1> dbg:fun2ms(fun([M]) when map_size(M#{a => b}) > 2 -> true end).
Error: the language element map (in guard) cannot be translated into match_spec
{error,transform_error}
However, creating a map in a guard is allowed:
1> dbg:fun2ms(fun([M]) when map_size(#{a => b}) > 2 -> true end).
[{['$1'],[{'>',{map_size,#{a => b}},2}],[true]}]
Variables from the environment can be imported, so this works:
1> X = 3.
3
2> dbg:fun2ms(fun([M,N]) when N > X -> return_trace() end).
[{['$1','$2'],[{'>','$2',{const,3}}],[{return_trace}]}]
The imported variables will be replaced by const
expressions, which
is consistent with the static scoping for Erlang funs.
In the body of the fun, only guard expressions and calls to the special functions for tracing are allowed.
Examples:
1> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]
2> dbg:fun2ms(fun(_) -> erlang:garbage_collect() end).
Error: fun containing the remote function call 'erlang:garbage_collect/0' (called in body) cannot be translated into match_spec
{error,transform_error}
Warning
If the parse transform is not applied to a module which calls
dbg:fun2ms/1
, the call will fail in runtime with abadarg
exception.
More information is available in the documentation for module ms_transform
in STDLIB.
-spec get_tracer() -> term().
Equivalent to get_tracer(node())
.
-spec get_tracer(Nodename) -> {ok, Tracer} when Nodename :: atom(), Tracer :: port() | pid() | {module(), term()}.
Returns the process, port, or tracer module to which all trace messages are sent.
-spec h() -> ok.
Gives a list of items for brief online help.
h
stands for help.
-spec h(Item) -> ok when Item :: atom().
Gives a brief help text for functions in the dbg
module.
h
stands for help.
The available items can be listed by calling dbg:h/0
.
-spec i() -> ok.
Displays information about all traced processes and ports.
i
stands for information.
-spec ln() -> ok.
Shows the list of traced nodes on the console.
ln
stands for list nodes.
-spec ltp() -> ok.
Lists all match specifications previously used in the session.
ltp
stands for list trace patterns.
This function lists all match specifications previously saved during
calls to tp/2
and tpl/2
, as well as all built-in match
specifications. This avoids having to re-type complicated match
specifications. Note that the match specifications are lost if
stop/0
is called.
Match specifications can be saved in a file (if a read-write file system is
present) for use in later debugging sessions; see wtp/1
and rtp/1
.
There are three built-in trace patterns:
exception_trace
,x
- sets a trace which will show function names, parameters, return values, and exceptions raised from functionscaller_trace
,c
- sets a trace that displays function names, parameters, and information about which function called itcaller_exception_trace
,cx
- combinesexception_trace
andcaller_trace
Here is an example that shows how to use a built-in match specification:
1> dbg:tracer().
{ok,<0.90.0>}
2> dbg:tp(lists, seq, 2, cx).
{ok,[{matched,nonode@nohost,1},{saved,cx}]}
3> dbg:p(self(), call).
{ok,[{matched,nonode@nohost,1}]}
4> lists:seq(1, 5).
(<0.88.0>) call lists:seq(1,5) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
[1,2,3,4,5]
(<0.88.0>) returned from lists:seq/2 -> [1,2,3,4,5]
Adds a remote node (Nodename
) to the list of nodes where tracing is
performed.
n
stands for node.
The dbg
server keeps a list of nodes where tracing should be
performed. Whenever a tp/2
call or a p/2
call is made, it is
executed for all nodes in this list including the local node (except
for p/2
with a specific pid/0
or port/0
as first argument,
in which case the command is executed only on the node where the
designated process or port resides).
When this function is called, it starts a tracer process on the remote
node, which will send all trace messages to the tracer process on the
local node (via the Erlang distribution). If no tracer process is
running on the local node, the error reason no_local_tracer
is
returned. The tracer process on the local node must be started with
the tracer/0,2
function.
If Nodename
is the local node, the error reason cant_add_local_node
is
returned.
If a trace port (see trace_port/2
) is running on the local node, remote nodes
cannot be traced with a tracer process. The error reason
cant_trace_remote_pid_to_local_port
is returned. However, a trace port can be
started on the remote node with the tracer/3
function.
The function will also return an error if the node Nodename
is not reachable.
Equivalent to p(Item, [m])
.
-spec p(Item :: term(), Flags :: term()) -> {ok, MatchDesc} | {error, term()} when MatchDesc :: [MatchNum], MatchNum :: {matched, node(), integer()} | {matched, node(), 0, RPCError}, RPCError :: term().
Traces Item
in accordance to the value specified by Flags
.
p
stands for process.
The following kind of values are allowed for Item
:
pid/0
orport/0
- The corresponding process or port is traced. The process or port can be a remote process or port (on another Erlang node). The node must be in the list of traced nodes (seen/1
andtracer/3
).all
- All processes and ports in the system as well as all processes and ports created hereafter are to be traced.processes
- All processes in the system as well as all processes created hereafter are to be traced.ports
- All ports in the system as well as all ports created hereafter are to be traced.new
- All processes and ports created after the call are to be traced.new_processes
- All processes created after the call are to be traced.new_ports
- All ports created after the call are to be traced.existing
- All existing processes and ports are traced.existing_processes
- All existing processes are traced.existing_ports
- All existing ports are traced.atom/0
- The process or port with the corresponding registered name is traced. The process or port can on another Erlang node. The node must be in the list of traced nodes (seen/1
andtracer/3
).integer/0
- The process<0.Item.0>
is traced.{X, Y, Z}
- The process<X.Y.Z>
is traced.string/0
- If theItem
is a string "<X.Y.Z>" as returned frompid_to_list/1
, the process<X.Y.Z>
is traced.
When enabling an Item
that represents a group of processes, the Item
is
enabled on all nodes added with the n/1
or tracer/3
function.
Flags
can be a single atom or a list of flags. The available flags are:
s (send)
- Traces the messages the process or port sends.r (receive)
- Traces the messages the process or port receives.m (messages)
- Traces the messages the process or port receives and sends.c (call)
- Traces global function calls for the process according to the trace patterns set in the system (seetp/2
).p (procs)
- Traces process related events to the process.ports
- Traces port related events to the port.sos (set on spawn)
- Lets all processes created by the traced process inherit the trace flags of the traced process.sol (set on link)
- Lets another process,P2
, inherit the trace flags of the traced process whenever the traced process links toP2
.sofs (set on first spawn)
- This is the same assos
, but only for the first process spawned by the traced process.sofl (set on first link)
- This is the same assol
, but only for the first call tolink/1
by the traced process.all
- Sets all flags exceptsilent
.clear
- Clears all flags.
The list can also include any of the flags allowed in trace:process/4
and
trace:port/4
.
This function returns either an error tuple or an {ok, List}
tuple. The List
consists of specifications of how many processes and ports that matched (in the
case of a single pid exactly 1). The specification of matched processes is
{matched, Node, N}
. If the remote processor call (using rpc
) to a remote node
fails, the rpc
error message is returned as the fourth element in the tuple
and the number of matched processes is 0.
Reads match specifications from a text file (possibly) generated by
the wtp/1
function.
rtp
stands for read trace patterns.
The function verifies that the syntax of all match specifications are correct. If any error in any match specification is found, none of the match specifications are added to the list of saved match specifications for the running system.
The match specifications in the file are merged with the current match
specifications, so that no duplicates are generated. Use ltp/0
to see what
numbers were assigned to the specifications from the file.
The function will return an error tuple, either due to I/O problems
(like a non-existing or non-readable file) or due to file format
problems. In the latter case, Reason
is in a more or less textual
format, giving a hint to what is causing the problem.
Runs dbg
commands using the provides session, or
creates a session for the duration of the call if a session name
is provided.
Any dbg
function that is called with in the provided fun
will use the session/0
provided instead of the default
dbg
session. This means that the tracing will be isolated
from other tracing users on the system.
The function returns the term that the fun returns.
Example:
1> S = dbg:session_create(my_session).
<0.91.0>
2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
{ok,[{matched,nonode@nohost,2},{saved,x}]}
3> lists:seq(1, 10).
(<0.89.0>) call lists:seq(1,10)
(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
4> dbg:session_destroy(S).
ok
The state of the session/0
is preserved in between session/2
calls, so
you can call session/2
multiple when debugging you application.
Example:
1> S = dbg:session_create(my_session).
<0.91.0>
%% Setup the initial traces
2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
{ok,[{matched,nonode@nohost,2},{saved,x}]}
3> lists:seq(1, 3).
(<0.89.0>) call lists:seq(1,3)
(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
[1,2,3]
%% Add an additional trace pattern
4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
ok
5> lists:seq(1, 3).
(<0.89.0>) call lists:seq(1,3)
(<0.89.0>) call lists:seq_loop(3,3,[])
(<0.89.0>) call lists:seq_loop(1,1,[2,3])
(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
[1,2,3]
6> dbg:session_destroy(S).
ok
Note
The session functionality is experimental in Erlang/OTP 27 and may change in future releases without notice.
Create a new dbg
session with the given Name
.
The session is linked with the calling process and will be
Multiple sessions can have the same name.
Note
The session functionality is experimental in Erlang/OTP 27 and may change in future releases without notice.
-spec session_destroy(Session :: session()) -> ok.
Destroys a dbg session/0
.
This will terminate all started processes and destroy the trace:session/0
.
-spec stop() -> ok.
Stops the dbg
server, clears all trace flags for all processes, clears all
trace patterns for all functions, clears trace patterns for send/receive, shuts
down all trace clients, and closes all trace ports.
-spec stop_trace_client(Pid) -> ok when Pid :: pid().
Shuts down a previously started trace client.
The Pid
argument is the process id returned from the
trace_client/2
or trace_client/3
call.
-spec tp(Module | {Module, Function, Arity}, MatchSpec) -> {ok, match_desc()} | {error, term()} when Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity(), MatchSpec :: tp_match_spec().
Enables call trace for one or more exported functions specified by ModuleOrMFA
.
If ModuleOrMFA
is an atom (a module name), this function call is equivalent to
tp({ModuleOrMFA, '_', '_'}, MatchSpec)
.
Otherwise, ModuleOrMFA
should be {Module, Function, Arity}
.
tp
stands for trace pattern.
All exported functions matching the {Module, Function, Arity}
argument will be concerned, but the match specification may further
narrow down the set of function calls generating trace messages.
For a description of the format for the MatchSpec
argument, see
Match Specifications in Erlang, which explains the
general match specification language. The most common generic match
specifications used can be found as built-in aliases; see ltp/0
below for
details.
The Module, Function and/or Arity parts of the tuple may be specified
as the atom '_'
which is a wildcard matching all modules, functions,
or arities. Note that if the Module
is specified as '_'
, the
Function
and Arity
parts must be specified as '_'
as well. The
same holds for the Function
in relation to Arity
.
All nodes added with n/1
or tracer/3
will be affected by this call, and if
Module
is not '_'
the module will be loaded on all nodes.
The function returns either an error tuple or an {ok, List}
tuple. The List
consists of specifications of how many functions that matched, in the same way
as the processes and ports are presented in the return value of p/2
.
There may be a tuple {saved, N}
in the return value, if the MatchSpec
is not
[]
. The integer N
can then be used in subsequent calls to this function
and will stand as an "alias" for the given expression.
If the match specification is invalid, an {error, Errors}
tuple is
returned. Errors
is as a list of tuples {error, string()}
, where
the string is a textual explanation of the compilation error. For
example:
1> dbg:tp({dbg,ltp,0},[{[],[],[{message, two, arguments}, {noexist}]}]).
{error,
[{error,"Special form 'message' called with wrong number of
arguments in {message,two,arguments}."},
{error,"Function noexist/1 does_not_exist."}]}
-spec tp(Module :: tp_module(), Function :: tp_function(), MatchSpec :: tp_match_spec()) -> {ok, match_desc()} | {error, term()}.
Equivalent to tp({Module, Function, '_'}, MatchSpec)
.
-spec tp(Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity(), MatchSpec :: tp_match_spec()) -> {ok, match_desc()} | {error, term()}.
Equivalent to tp({Module, Function, Arity}, MatchSpec)
.
-spec tpe(Event, MatchSpec) -> {ok, MatchDesc :: match_desc()} | {error, term()} when Event :: send | 'receive', MatchSpec :: tp_match_spec().
Associates a match specification with trace event send
or
'receive'
.
tpe
stands for trace pattern event.
By default all executed
send
and 'receive'
events are traced if enabled for a process. A match
specification can be used to filter traced events based on sender, receiver,
and/or message content.
For a description of the format for the MatchSpec
argument, see
Match Specifications in Erlang, which explains the
general match specification language.
For send
, the matching is done on the list [Receiver, Msg]
. Receiver
is
the process or port identity of the receiver and Msg
is the message term. The
pid of the sending process can be accessed with the guard function self/0
.
For 'receive'
, the matching is done on the list [Node, Sender, Msg]
. Node
is the node name of the sender. Sender
is the process or port identity of the
sender, or the atom undefined
if the sender is not known (which may be the
case for remote senders). Msg
is the message term. The pid of the receiving
process can be accessed by calling self/0
.
All nodes added with n/1
or tracer/3
will be affected by this call.
The return value is the same as for tp/2
. The number of matched events is
always 1 as tpe/2
does not accept any form of wildcards
for argument Event
.
-spec tpl(Module | {Module, Function :: tp_function(), Arity :: tp_arity()}, MatchSpec :: tp_match_spec()) -> {ok, MatchDesc :: term()} | {error, term()} when Module :: tp_module().
Enables call trace for one or more functions specified by ModuleOrMFA
.
If ModuleOrMFA
is an atom (a module name), this function call is equivalent to
tpl({ModuleOrMFA, '_', '_'}, MatchSpec)
.
Otherwise, ModuleOrMFA
should be {Module, Function, Arity}
.
tpl
stands for trace pattern local.
This function works as tp/2
, but enables tracing for local or remote calls
to both local and exported functions.
-spec tpl(Module :: tp_module(), Function :: tp_function(), MatchSpec :: tp_match_spec()) -> {ok, match_desc()} | {error, term()}.
Equivalent to tpl({Module, Function, '_'}, MatchSpec)
.
-spec tpl(Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity(), MatchSpec :: tp_match_spec()) -> {ok, match_desc()} | {error, term()}.
Equivalent to tpl({Module, Function, Arity}, MatchSpec)
.
-spec trace_client(ip, IPClientPortSpec) -> pid() when IPClientPortSpec :: PortNumber | {Hostname, PortNumber}, PortNumber :: integer(), Hostname :: string(); (Type, Parameters) -> pid() when Type :: file | follow_file, Parameters :: Filename | WrapFilesSpec, Filename :: file:name_all(), WrapFilesSpec :: trace_wrap_files_spec().
Starts a trace client that reads the output created by a trace port
driver (see trace_port/2
) and handles it in mostly the same way as a
tracer process created by the tracer/0
function.
If Type
is file
, the client reads all trace messages stored in the
file named Filename
or specified by WrapFilesSpec
(must be the
same as used when creating the trace) and lets the default handler
function format the messages on the console. This is one way to
interpret the data stored in a file by the file trace port driver.
If Type
is follow_file
, the client behaves as in the file
case, but keeps
trying to read (and process) more data from the file until stopped by
stop_trace_client/1
. WrapFilesSpec
is not allowed as second argument for
this Type
.
If Type
is ip
, the client connects to the TCP/IP port PortNumber
on the
host Hostname
, from where it reads trace messages until the TCP/IP connection
is closed. If no Hostname
is specified, the local host is assumed.
As an example, one can let trace messages be sent over the network to another Erlang node (preferably not distributed), where the formatting occurs.
On the node stack
there exists an Erlang node ant@stack
. In the
shell, type the following:
ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
<0.17.0>
ant@stack> dbg:p(self(), send).
{ok,1}
All trace messages are now sent to the trace port driver, which in turn listens for connections on the TCP/IP port 4711. If we want to see the messages on another node, preferably on another host, we do like this:
1> dbg:trace_client(ip, {"stack", 4711}).
<0.42.0>
If we now send a message from the shell on the node ant@stack
, where all sends
from the shell are traced:
ant@stack> self() ! hello.
hello
The following will appear at the console on the node that started the trace client:
(<0.23.0>) <0.23.0> ! hello
(<0.23.0>) <0.22.0> ! {shell_rep,<0.23.0>,{value,hello,[],[]}}
The last line is generated due to internal message passing in the Erlang shell. The pids will vary.
-spec trace_client(ip, IPClientPortSpec, HandlerSpec) -> pid() when IPClientPortSpec :: PortNumber | {Hostname, PortNumber}, PortNumber :: integer(), Hostname :: string(), HandlerSpec :: handler_spec(); (Type, Parameters, HandlerSpec) -> pid() when Type :: file | follow_file, Parameters :: Filename | WrapFilesSpec, Filename :: string() | [string()] | atom(), WrapFilesSpec :: trace_wrap_files_spec(), HandlerSpec :: handler_spec().
This function works exactly as trace_client/2
, but allows you to write your
own handler function.
The handler function works mostly as the one described in tracer/2
,
but must also be prepared to handle trace messages of the form {drop, N}
, where N
is the number of dropped messages. This pseudo trace
message will only occur if the ip
trace driver is used.
For trace type file
, the pseudo trace message end_of_trace
will appear at
the end of the trace. The return value from the handler function is in this case
ignored.
-spec trace_port(ip, IpPortSpec) -> fun(() -> port()) when IpPortSpec :: PortNumber | {PortNumber, QueSize}, PortNumber :: integer(), QueSize :: integer(); (file, Parameters) -> fun(() -> port()) when Parameters :: Filename | WrapFilesSpec, Filename :: file:name_all(), WrapFilesSpec :: trace_wrap_files_spec().
Creates a trace-port-generating fun that is suitable as the
second argument to tracer/2
.
Example:
dbg:tracer(port, dbg:trace_port(ip, 4711)).
A trace port is an Erlang port to a dynamically linked-in driver that handles trace messages directly, without the overhead of sending them as messages to an Erlang process. Using a trace port significantly lowers the overhead imposed by tracing.
Two trace drivers are currently implemented: the file
and the ip
trace drivers.
The file
driver sends all trace messages into one or
several binary files, from where they later can be fetched and
processed with the trace_client/2
function.
The ip
driver opens a TCP/IP port listening port. When a client
(preferably started by calling trace_client/2
on another Erlang
node) connects, all trace messages are sent over the IP network for
further processing by the remote client.
The file
trace driver expects a filename or a wrap files
specification as parameter. A file is written with a high degree of
buffering, which is why there is no guarantee that all are saved in the
file in case of a system crash.
A wrap files specification is used to limit the disk space consumed by the
trace. The trace is written to a limited number of files each with a limited
size. The actual filenames are Filename ++ SeqCnt ++ Suffix
, where SeqCnt
counts as a decimal string from 0
to WrapCnt
and then around again from 0
.
When a trace term written to the current file makes it longer than WrapSize
,
that file is closed, and if the number of files in this wrap trace is as many as
WrapCnt
the oldest file is deleted, and a new file is opened to become the
current. Thus, when a wrap trace has been stopped, there are at most WrapCnt
trace files saved with a size of at least WrapSize
(but not much larger),
except for the last file that might even be empty. The default values are
WrapSize = 128*1024
and WrapCnt = 8
.
The SeqCnt
values in the filenames are all in the range 0
through WrapCnt
with a gap in the circular sequence. The gap is needed to find the end of the
trace.
If the WrapSize
is specified as {time, WrapTime}
, the current file is closed
when it has been open more than WrapTime
milliseconds, regardless of it being
empty or not.
The ip
trace driver has a queue of QueSize
messages waiting to be delivered.
If the driver cannot deliver messages as fast as they are produced by the
runtime system, a special message is sent, which indicates how many messages
that are dropped. That message will arrive at the handler function specified in
trace_client/3
as the tuple {drop, N}
where N
is the number of consecutive
messages dropped. In case of heavy tracing, drops are likely to occur, and they
surely occur if no client is reading the trace messages. The default value of
QueSize
is 200.
Equivalent to trace_port_control(node(), Operation)
.
-spec trace_port_control(Nodename :: node(), Operation :: term()) -> ok | {ok, Result :: term()} | {error, Reason :: term()}.
This function is used to do a control operation on the active trace port driver
on the given node (Nodename
).
Which operations are allowed as well as their return values depend on which trace driver is used.
Returns either ok
or {ok, Result}
if the operation was successful, or
{error, Reason}
if the current tracer is a process, or if it is a port not
supporting the operation.
The allowed values for Operation
are:
flush
- This function is used to flush the internal buffers held by a trace port driver. Currently only thefile
trace driver supports this operation. Returnsok
.get_listen_port
- Returns{ok, IpPort}
whereIpPort
is the IP port number used by the driver listen socket. Only theip
trace driver supports this operation.
-spec tracer() -> {ok, pid()} | {error, already_started}.
Starts a server on the local node that will be the recipient of all trace messages.
All subsequent calls to p/2
will result in messages sent
to the newly started trace server.
A trace server started in this way will simply display the formatted
trace messages the Erlang shell (that is, using io:format/2
). See tracer/2
for a description of how the trace message handler can be customized.
To start a similar tracer on a remote node, use n/1
.
-spec tracer(port, PortGenerator) -> {ok, pid()} | {error, Error :: term()} when PortGenerator :: fun(() -> port()); (process, HandlerSpec) -> {ok, pid()} | {error, Error :: term()} when HandlerSpec :: {HandlerFun, InitialData :: term()}, HandlerFun :: fun((Event :: term(), Data :: term()) -> NewData :: term()); (module, ModuleSpec) -> {ok, pid()} | {error, Error :: term()} when ModuleSpec :: fun(() -> {TracerModule, TracerState}) | {TracerModule, TracerState}, TracerModule :: atom(), TracerState :: term(); (file, Filename) -> {ok, pid()} | {error, Error :: term()} when Filename :: file:name_all().
Starts a tracer server with additional parameters on the local node.
Type
indicates how trace messages should be handled:
process
- by a receiving processport
- by a port; seetrace_port/2
module
- by a tracer module; seeerl_tracer
file
- by printing them to a file
If Type
is process
, Data
should be a message handler function
(HandlerSpec
). The handler function, which should be a fun
taking two
arguments, will be called for each trace message, with the first argument
containing the message as it is and the second argument containing the return
value from the last invocation of the fun. The initial value of the second
parameter is specified in the InitialData
part of the HandlerSpec
. The
HandlerFun
can choose any appropriate action to take when invoked, and can
save a state for the next invocation by returning it.
If Type
is port
, then the second parameter should be a fun which takes no
arguments and returns a newly opened trace port when called. Such a fun is
preferably generated by calling trace_port/2
.
If Type
is module
, Data
should be either a tuple describing the
erl_tracer
module to be used for tracing and the state to be used
for that tracer module, or a fun returning that kind of tuple.
if Type
is file
, Data
should be a filename specifying a file
where all the traces are to be printed.
If an error is returned, it can either be because a tracer server is
already running ({error,already_started}
), or because
HandlerFun
raised an exception.
To start a similar tracer on a remote node, use tracer/3
.
-spec tracer(Nodename :: node(), Type :: term(), Data :: term()) -> {ok, Nodename :: node()} | {error, Reason :: term()}.
This function is equivalent to tracer/2
, but acts on the given node.
A tracer is started on the node (Nodename
) and the node is added to
the list of traced nodes.
Note
This function is not equivalent to
n/1
. Whilen/1
starts a process tracer which redirects all trace information to a process tracer on the local node (that is, the trace control node),tracer/3
starts any type of tracer, independent of the type of tracer on the trace control node.
For details, see tracer/2
.
Saves all match specifications saved during the session (by calls to
tp/2
or tpl/2
), as well as built-in match specifications, in a text
file with the name designated by Name
.
wtp
stands for write trace patterns.
The format of the file is textual, which means that it can be edited
with a text editor, and then restored with rtp/1
.
Each match specification in the file ends with a period (.
) and
new (syntactically correct) match specifications can be added to the
file manually.
The function returns ok
, or an error tuple where the second element
indicates the reason that writing the file failed.