runtime_tools

v2.3.1

dbg

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.

The Tracing in Erlang with dbg Users guide explains how to quickly get started on tracing function calls, complex systems and more.

Summary

Types

built_in_alias()

handler_spec()

match_desc()

match_info()

match_num()

match_pattern()

match_spec()

session()

A dbg session that can be used by session/2 to create isolated debugging sessions.

tp_arity()

tp_function()

tp_id()

tp_match_spec()

tp_module()

trace_wrap_file_size()

trace_wrap_files_spec()

Functions

c(Mod, Fun, Args)

Equivalent to c(Mod, Fun, Args, all).

c(Mod, Fun, Args, Flags)

Evaluates the expression apply(Mod, Fun, Args) with the trace flags in Flags set.

cn(Nodename)

Clears a node from the list of traced nodes.

ctp()

Equivalent to ctp({'_', '_', '_'}).

ctp(ModuleOrMFA)

Disables call tracing for one or more functions specified by ModuleOrMFA.

ctp(Module, Function)

Equivalent to ctp({Module, Function, '_'}).

ctp(Module, Function, Arity)

Equivalent to ctp({Module, Function, Arity}).

ctpe(Event)

Clears match specifications for the specified trace event (send or 'receive'), reverting to the default of tracing all triggered events.

ctpg()

Equivalent to ctpg({'_', '_', '_'}).

ctpg(ModuleOrMFA)

Disables global call tracing for one or more functions specified by ModuleOrMFA.

ctpg(Module, Function)

Equivalent to ctpg({Module, Function, '_'}).

ctpg(Module, Function, Arity)

Equivalent to ctpg({Module, Function, Arity}).

ctpl()

Equivalent to ctpl({'_', '_', '_'}).

ctpl(ModuleOrMFA)

Disables local call tracing for one or more functions specified by ModuleOrMFA.

ctpl(Module, Function)

Equivalent to ctpl({Module, Function, '_'}).

ctpl(Module, Function, Arity)

Equivalent to ctpl({Module, Function, Arity}).

dtp()

Forgets all match specifications saved during calls to tp/2.

dtp(N)

Forgets a specific match specification saved during calls to tp/2.

flush_trace_port()

Equivalent to flush_trace_port(node()).

flush_trace_port(Nodename)

Equivalent to trace_port_control(Nodename, flush).

fun2ms(LiteralFun)

Pseudo function that by means of a parse transform translates the literal fun typed as parameter in the function call to a match specification.

get_tracer()

Equivalent to get_tracer(node()).

get_tracer(Nodename)

Returns the process, port, or tracer module to which all trace messages are sent.

h()

Gives a list of items for brief online help.

h(Item)

Gives a brief help text for functions in the dbg module.

i()

Displays information about all traced processes and ports.

ln()

Shows the list of traced nodes on the console.

ltp()

Lists all match specifications previously used in the session.

n(Nodename)

Adds a remote node (Nodename) to the list of nodes where tracing is performed.

p(Item)

Equivalent to p(Item, [m]).

p(Item, Flags)

Traces Item in accordance to the value specified by Flags.

rtp(Name)

Reads match specifications from a text file (possibly) generated by the wtp/1 function.

session(Session, Fun)

Runs dbg commands using the provides session, or creates a session for the duration of the call if a session name is provided.

session_create(Name)

Create a new dbg session with the given Name.

session_destroy(Session)

Destroys a dbg session/0.

stop()

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.

stop_trace_client(Pid)

Shuts down a previously started trace client.

tp(ModuleOrMFA, MatchSpec)

Enables call trace for one or more exported functions specified by ModuleOrMFA.

tp(Module, Function, MatchSpec)

Equivalent to tp({Module, Function, '_'}, MatchSpec).

tp(Module, Function, Arity, MatchSpec)

Equivalent to tp({Module, Function, Arity}, MatchSpec).

tpe(Event, MatchSpec)

Associates a match specification with trace event send or 'receive'.

tpl({Module, Function, Arity}, MatchSpec)

Enables call trace for one or more functions specified by ModuleOrMFA.

tpl(Module, Function, MatchSpec)

Equivalent to tpl({Module, Function, '_'}, MatchSpec).

tpl(Module, Function, Arity, MatchSpec)

Equivalent to tpl({Module, Function, Arity}, MatchSpec).

trace_client(Type, Parameters)

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.

trace_client(Type, Parameters, HandlerSpec)

This function works exactly as trace_client/2, but allows you to write your own handler function.

trace_port(Type, Parameters)

Creates a trace-port-generating fun that is suitable as the second argument to tracer/2.

trace_port_control(Operation)

Equivalent to trace_port_control(node(), Operation).

trace_port_control(Nodename, Operation)

This function is used to do a control operation on the active trace port driver on the given node (Nodename).

tracer()

Starts a server on the local node that will be the recipient of all trace messages.

tracer(Type, Data)

Starts a tracer server with additional parameters on the local node.

tracer(Nodename, Type, Data)

This function is equivalent to tracer/2, but acts on the given node.

wtp(Name)

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.

Types

built_in_alias()

(not exported)

-type built_in_alias() :: x | c | cx.

handler_spec()

(not exported)

-type handler_spec() ::
          {HandlerFun :: fun((Event :: term(), Data :: term()) -> NewData :: term()),
           InitialData :: term()}.

match_desc()

(not exported)

-type match_desc() :: [match_info()].

match_info()

(not exported)

-type match_info() :: {saved, tp_id()} | match_num().

match_num()

(not exported)

-type match_num() :: {matched, node(), integer()} | {matched, node(), 0, RPCError :: term()}.

match_pattern()

(not exported)

-type match_pattern() :: atom() | list().

match_spec()

-type match_spec() :: [{match_pattern(), [_], [_]}].

session()

-opaque session()

A dbg session that can be used by session/2 to create isolated debugging sessions.

tp_arity()

(not exported)

-type tp_arity() :: arity() | '_'.

tp_function()

(not exported)

-type tp_function() :: atom() | '_'.

tp_id()

(not exported)

-type tp_id() :: pos_integer().

tp_match_spec()

(not exported)

-type tp_match_spec() :: tp_id() | built_in_alias() | [] | match_spec().

tp_module()

(not exported)

-type tp_module() :: module() | '_'.

trace_wrap_file_size()

(not exported)

-type trace_wrap_file_size() :: non_neg_integer() | {time, WrapTime :: pos_integer()}.

trace_wrap_files_spec()

(not exported)

-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

c(Mod, Fun, Args)

-spec c(Mod :: module(), Fun :: atom(), Args :: [term()]) -> term().

Equivalent to c(Mod, Fun, Args, all).

c(Mod, Fun, Args, Flags)

-spec c(Mod :: module(), Fun :: atom(), Args :: [term()], Flags :: term()) -> term().

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.

cn(Nodename)

-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.

ctp()

-spec ctp() -> {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctp({'_', '_', '_'}).

ctp(ModuleOrMFA)

-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.

ctp(Module, Function)

-spec ctp(Module :: tp_module(), Function :: tp_function()) ->
             {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctp({Module, Function, '_'}).

ctp(Module, Function, Arity)

-spec ctp(Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity()) ->
             {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctp({Module, Function, Arity}).

ctpe(Event)

(since OTP 19.0)

-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.

ctpg()

-spec ctpg() -> {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctpg({'_', '_', '_'}).

ctpg(ModuleOrMFA)

-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).

ctpg(Module, Function)

-spec ctpg(Module :: tp_module(), Function :: tp_function()) ->
              {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctpg({Module, Function, '_'}).

ctpg(Module, Function, Arity)

-spec ctpg(Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity()) ->
              {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctpg({Module, Function, Arity}).

ctpl()

-spec ctpl() -> {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctpl({'_', '_', '_'}).

ctpl(ModuleOrMFA)

-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).

ctpl(Module, Function)

-spec ctpl(Module :: tp_module(), Function :: tp_function()) ->
              {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctpl({Module, Function, '_'}).

ctpl(Module, Function, Arity)

-spec ctpl(Module :: tp_module(), Function :: tp_function(), Arity :: tp_arity()) ->
              {ok, MatchDesc :: match_desc()} | {error, term()}.

Equivalent to ctpl({Module, Function, Arity}).

dtp()

-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.

dtp(N)

-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.

flush_trace_port()

-spec flush_trace_port() -> term().

Equivalent to flush_trace_port(node()).

flush_trace_port(Nodename)

-spec flush_trace_port(Nodename :: node()) -> ok | {error, Reason :: term()}.

Equivalent to trace_port_control(Nodename, flush).

fun2ms(LiteralFun)

-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 a badarg exception.

More information is available in the documentation for module ms_transform in STDLIB.

get_tracer()

-spec get_tracer() -> term().

Equivalent to get_tracer(node()).

get_tracer(Nodename)

-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.

h()

-spec h() -> ok.

Gives a list of items for brief online help.

h stands for help.

h(Item)

-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.

i()

-spec i() -> ok.

Displays information about all traced processes and ports.

i stands for information.

ln()

-spec ln() -> ok.

Shows the list of traced nodes on the console.

ln stands for list nodes.

ltp()

-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 functions

caller_trace, c - sets a trace that displays function names, parameters, and information about which function called it

caller_exception_trace, cx - combines exception_trace and caller_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]

n(Nodename)

-spec n(Nodename) -> {ok, Nodename} | {error, Reason} when Nodename :: node(), Reason :: term().

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.

p(Item)

-spec p(Item :: term()) -> {ok, MatchDesc :: term()} | {error, term()}.

Equivalent to p(Item, [m]).

p(Item, Flags)

-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 or port/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 (see n/1 and tracer/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 (see n/1 and tracer/3).

integer/0 - The process <0.Item.0> is traced.

{X, Y, Z} - The process <X.Y.Z> is traced.

string/0 - If the Item is a string "<X.Y.Z>" as returned from pid_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 (see tp/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 to P2.

sofs (set on first spawn) - This is the same as sos, but only for the first process spawned by the traced process.

sofl (set on first link) - This is the same as sol, but only for the first call to link/1 by the traced process.

all - Sets all flags except silent.

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.

rtp(Name)

-spec rtp(Name) -> ok | {error, Error} when Name :: string(), Error :: term().

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.

session(Session, Fun)

(since OTP 27.0)

-spec session(atom(), fun(() -> term())) -> term();
             (session(), fun(() -> term())) -> term().

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.

session_create(Name)

(since OTP 27.0)

-spec session_create(atom()) -> session().

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.

session_destroy(Session)

(since OTP 27.0)

-spec session_destroy(Session :: session()) -> ok.

Destroys a dbg session/0.

This will terminate all started processes and destroy the trace:session/0.

stop()

-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.

stop_trace_client(Pid)

-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.

tp(ModuleOrMFA, MatchSpec)

-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."}]}

tp(Module, Function, MatchSpec)

-spec tp(Module :: tp_module(), Function :: tp_function(), MatchSpec :: tp_match_spec()) ->
            {ok, match_desc()} | {error, term()}.

Equivalent to tp({Module, Function, '_'}, MatchSpec).

tp(Module, Function, Arity, 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).

tpe(Event, MatchSpec)

(since OTP 19.0)

-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.

tpl({Module, Function, Arity}, MatchSpec)

-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.

tpl(Module, Function, MatchSpec)

-spec tpl(Module :: tp_module(), Function :: tp_function(), MatchSpec :: tp_match_spec()) ->
             {ok, match_desc()} | {error, term()}.

Equivalent to tpl({Module, Function, '_'}, MatchSpec).

tpl(Module, Function, Arity, 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).

trace_client(Type, Parameters)

-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.

trace_client(Type, Parameters, HandlerSpec)

-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.

trace_port(Type, Parameters)

-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.

trace_port_control(Operation)

-spec trace_port_control(Operation :: term()) -> term().

Equivalent to trace_port_control(node(), Operation).

trace_port_control(Nodename, 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 the file trace driver supports this operation. Returns ok.

get_listen_port - Returns {ok, IpPort} where IpPort is the IP port number used by the driver listen socket. Only the ip trace driver supports this operation.

tracer()

-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.

tracer(Type, Data)

-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 process

port - by a port; see trace_port/2

module - by a tracer module; see erl_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.

tracer(Nodename, Type, Data)

-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. While n/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.

wtp(Name)

-spec wtp(Name) -> ok | {error, IOError} when Name :: string(), IOError :: term().

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.

dyntrace

Interface to dynamic tracing

This module implements interfaces to dynamic tracing, should such be compiled into the virtual machine. For a standard and/or commercial build, no dynamic tracing is available, in which case none of the functions in this module is usable or give any effect.

Should dynamic tracing be enabled in the current build, either by configuring with ./configure --with-dynamic-trace=dtrace or with ./configure --with-dynamic-trace=systemtap, the module can be used for two things:

Trigger the user-probe user_trace_i4s4 in the NIF library dyntrace.so by calling dyntrace:p/{1,2,3,4,5,6,7,8}.

Set a user specified tag that will be present in the trace messages of both the efile_drv and the user-probe mentioned above.

Both building with dynamic trace probes and using them is experimental and unsupported by Erlang/OTP. It is included as an option for the developer to trace and debug performance issues in their systems.

The original implementation is mostly done by Scott Lystiger Fritchie as an Open Source Contribution and it should be viewed as such even though the source for dynamic tracing as well as this module is included in the main distribution. However, the ability to use dynamic tracing of the virtual machine is a very valuable contribution which OTP has every intention to maintain as a tool for the developer.

How to write d programs or systemtap scripts can be learned from books and from a lot of pages on the Internet. This manual page does not include any documentation about using the dynamic trace tools of respective platform. However, the examples directory of the runtime_tools application contains comprehensive examples of both d and systemtap programs that will help you get started. Another source of information is the dtrace and systemtap chapters in the Runtime Tools Users' Guide.

Summary

Types

probe_arg()

Functions

available()

This function uses the NIF library to determine if dynamic tracing is available.

get_tag()

This function returns the user tag set in the current process. If no tag is set or dynamic tracing is not available, it returns undefined.

p()

Calling this function triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing only the user tag and zeroes/empty strings in all other fields.

p(Arg)

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer or string parameter in the first integer/string field.

p(Arg1, Arg2)

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

p(Arg1, Arg2, Arg3)

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

p(Arg1, Arg2, Arg3, Arg4)

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

p(Int, Arg1, Arg2, Arg3, String)

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

p(Int1, Int2, Arg1, Arg2, String1, String2)

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

p(Int1, Int2, Int3, Arg, String1, String2, String4)

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

p(Int1, Int2, Int3, Int4, String1, String2, String3, String4)

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing all the integer() and string() parameters provided, as well as any user tag set in the current process.

put_tag(Item)

This function sets the user tag of the current process.

restore_tag(TagData)

Restores the previous state of user tags and their spreading as it was before a call to spread_tag/1.

spread_tag(boolean())

This function controls if user tags are to be spread to other processes with the next message.

Types

probe_arg()

(not exported) (since OTP R15B01)

-type probe_arg() :: integer() | iolist().

Functions

available()

(since OTP R15B01)

-spec available() -> true | false.

This function uses the NIF library to determine if dynamic tracing is available.

This function will throw an exception if the dyntrace NIF library could not be loaded by the on_load function in this module.

Use erlang:system_info(dynamic_trace) to determine whether the run-time system supports dynamic tracing.

get_tag()

(since OTP R15B01)

-spec get_tag() -> binary() | undefined.

This function returns the user tag set in the current process. If no tag is set or dynamic tracing is not available, it returns undefined.

This function returns the user tag set in the current process or, if no user tag is present, the last user tag sent to the process together with a message (in the same way as sequential trace tokens are spread to other processes together with messages. For an explanation of how user tags can be spread together with messages, see spread_tag/1. If no tag is found or dynamic tracing is not available, it returns undefined

p()

(since OTP R15B01)

-spec p() -> true | false | error | badarg.

Calling this function triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing only the user tag and zeroes/empty strings in all other fields.

p(Arg)

(since OTP R15B01)

-spec p(probe_arg()) -> true | false | error | badarg.

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer or string parameter in the first integer/string field.

p(Arg1, Arg2)

(since OTP R15B01)

-spec p(probe_arg(), probe_arg()) -> true | false | error | badarg.

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

integer() parameters should be put before any string() parameters.

That is, the following calls work:

dyntrace:p(1, "Hello")

dyntrace:p(1, 1)

dyntrace:p("Hello", "Again")

The following call is invalid because the string argument comes before the integer argument:

dyntrace:p("Hello", 1)

p(Arg1, Arg2, Arg3)

(since OTP R15B01)

-spec p(probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

integer() parameters should be put before any string() parameters.

p(Arg1, Arg2, Arg3, Arg4)

(since OTP R15B01)

-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

integer() parameters should be put before any string() parameters.

p(Int, Arg1, Arg2, Arg3, String)

(since OTP R15B01)

-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg()) ->
           true | false | error | badarg.

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

integer() parameters should be put before any string() parameters.

There can be no more than four parameters of each type, so the first parameter must be of type integer() and the last parameter of type string().

p(Int1, Int2, Arg1, Arg2, String1, String2)

(since OTP R15B01)

-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg()) ->
           true | false | error | badarg.

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

integer() parameters should be put before any string() parameters.

There can be no more than four parameters of each type, so the first two parameters must be of type integer() and the last two of type string().

p(Int1, Int2, Int3, Arg, String1, String2, String4)

(since OTP R15B01)

-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg()) ->
           true | false | error | badarg.

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of their respective type.

integer() parameters should be put before any string() parameters.

There can be no more than four parameters of each type, so the first three parameters must be of type integer() and the last three of type string().

p(Int1, Int2, Int3, Int4, String1, String2, String3, String4)

(since OTP R15B01)

-spec p(probe_arg(),
        probe_arg(),
        probe_arg(),
        probe_arg(),
        probe_arg(),
        probe_arg(),
        probe_arg(),
        probe_arg()) ->
           true | false | error | badarg.

Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing all the integer() and string() parameters provided, as well as any user tag set in the current process.

put_tag(Item)

(since OTP R15B01)

-spec put_tag(undefined | iodata()) -> binary() | undefined.

This function sets the user tag of the current process.

The user tag is a binary(), but can be specified as any iodata(), which is automatically converted to a binary by this function.

The user tag is provided to the user probes triggered by calls top dyntrace:p/{1,2,3,4,5,6,7,8} as well as probes in the efile driver. In the future, user tags might be added to more probes.

The old user tag (if any) is returned, or undefined if no user tag was present, or dynamic tracing is not enabled.

restore_tag(TagData)

(since OTP R15B01)

-spec restore_tag(true | {non_neg_integer(), binary() | []}) -> true.

Restores the previous state of user tags and their spreading as it was before a call to spread_tag/1.

Note that the restoring is not limited to the same process; one can utilize this to turn off spreding in one process and restore it in a newly created process that is is actually going to send messages:

f() ->
    TagData = dyntrace:spread_tag(false),
    spawn(fun() ->
             dyntrace:restore_tag(TagData),
             do_something()
          end),
    do_something_else(),
    dyntrace:restore_tag(TagData).

Correctly handling user tags and their spreading might take some effort, as Erlang programs tend to send and receive messages so that sometimes the user tag gets lost due to various things, like double receives or communication with a port (ports do not handle user tags, in the same way as they do not handle regular sequential trace tokens).

spread_tag(boolean())

(since OTP R15B01)

-spec spread_tag(boolean()) -> true | {non_neg_integer(), binary() | []}.

This function controls if user tags are to be spread to other processes with the next message.

Spreading of user tags work like spreading of sequential trace tokens, so that a received user tag will be active in the process until the next message arrives (if that message does not also contain the user tag).

This functionality is used when a client process communicates with a file i/o-server to spread the user tag to the I/O-server and then down to the efile driver. By using spread_tag/1 and restore_tag/1, one can enable or disable spreading of user tags to other processes and then restore the previous state of the user tag. The TagData returned from this call contains all previous information so the state (including any previously spread user tags) will be completely restored by a later call to restore_tag/1.

The file module already spreads tags, so there is no need to manually call this function to get user tags spread to the efile driver through that module.

The most use of this function would be if one, for example, uses the io module to communicate with an I/O-server for a regular file, such as in the following example:

f() ->
   {ok, F} = file:open("test.tst", [write]),
   Saved = dyntrace:spread_tag(true),
   io:format(F, "Hello world!", []),
   dyntrace:restore_tag(Saved),
   file:close(F).

In this example, any user tag set in the calling process will be spread to the I/O-server when the io:format/3 call is done.

instrument

Analysis and Utility Functions for Instrumentation

The module instrument contains support for studying the resource usage in an Erlang runtime system. Currently, only the allocation of memory can be studied.

Note

Since this module inspects internal details of the runtime system it may differ greatly from one version to another. We make no compatibility guarantees in this module.

See Also

erts_alloc(3), erl(1)

Summary

Types

allocation_origin()

allocation_summary()

A summary of allocated block sizes (including their headers) grouped by their Origin and Type.

block_histogram()

A histogram of block sizes where each interval's upper bound is twice as high as the one before it.

carrier_info_list()

AllocatorType is the type of the allocator that employs this carrier.

Functions

allocations()

Equivalent to allocations(#{}).

allocations(Options)

Returns a summary of all tagged allocations in the system, optionally filtered by allocator type and scheduler id.

carriers()

Equivalent to carriers(#{}).

carriers(Options)

Returns a summary of all carriers in the system, optionally filtered by allocator type and scheduler id.

Types

allocation_origin()

(not exported)

-type allocation_origin() :: atom() | mfa() | pid() | port().

allocation_summary()

(not exported)

-type allocation_summary() ::
          {HistogramStart :: non_neg_integer(),
           UnscannedSize :: non_neg_integer(),
           Allocations :: #{Origin :: allocation_origin() => #{Type :: atom() => block_histogram()}}}.

A summary of allocated block sizes (including their headers) grouped by their Origin and Type.

Origin is generally which NIF or driver that allocated the blocks, or 'system' if it could not be determined.

Type is the allocation category that the blocks belong to, e.g. db_term, message or binary. The categories correspond to those in erl_alloc.types.

If one or more carriers could not be scanned in full without harming the responsiveness of the system, UnscannedSize is the number of bytes that had to be skipped.

block_histogram()

(not exported)

-type block_histogram() :: tuple().

A histogram of block sizes where each interval's upper bound is twice as high as the one before it.

The upper bound of the first interval is provided by the function that returned the histogram, and the last interval has no upper bound.

For example, the histogram below has 40 (message) blocks between 128-256 bytes in size, 78 blocks between 256-512 bytes,2 blocks between 512-1024 bytes, and 2 blocks between 1-2KB.

> instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
{ok, {128, 0, #{ message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0}, ... } }}

carrier_info_list()

(not exported)

-type carrier_info_list() ::
          {HistogramStart :: non_neg_integer(),
           Carriers ::
               [{AllocatorType :: atom(),
                 InPool :: boolean(),
                 TotalSize :: non_neg_integer(),
                 UnscannedSize :: non_neg_integer(),
                 Allocations ::
                     [{Type :: atom(), Count :: non_neg_integer(), Size :: non_neg_integer()}],
                 FreeBlocks :: block_histogram()}]}.

AllocatorType is the type of the allocator that employs this carrier.

InPool is whether the carrier is in the migration pool.

TotalSize is the total size of the carrier, including its header.

Allocations is a summary of the allocated blocks in the carrier. Note that carriers may contain multiple different block types when carrier pools are shared between different allocator types (see the erts_alloc documentation for more details).

FreeBlocks is a histogram of the free block sizes in the carrier.

If the carrier could not be scanned in full without harming the responsiveness of the system, UnscannedSize is the number of bytes that had to be skipped.

Functions

allocations()

(since OTP 21.0)

-spec allocations() -> {ok, Result} | {error, Reason}
                     when Result :: allocation_summary(), Reason :: not_enabled.

Equivalent to allocations(#{}).

allocations(Options)

(since OTP 21.0)

-spec allocations(Options) -> {ok, Result} | {error, Reason}
                     when
                         Result :: allocation_summary(),
                         Reason :: not_enabled,
                         Options ::
                             #{scheduler_ids => [non_neg_integer()],
                               allocator_types => [atom()],
                               histogram_start => pos_integer(),
                               histogram_width => pos_integer(),
                               flags => [per_process | per_port | per_mfa]}.

Returns a summary of all tagged allocations in the system, optionally filtered by allocator type and scheduler id.

Only binaries and allocations made by NIFs and drivers are tagged by default, but this can be configured an a per-allocator basis with the +M<S>atags emulator option.

If the specified allocator types are not enabled, the call will fail with {error, not_enabled}.

The following options can be used:

allocator_types - The allocator types that will be searched.

Specifying a specific allocator type may lead to strange results when carrier migration between different allocator types has been enabled: you may see unexpected types (e.g. process heaps when searching binary_alloc), or fewer blocks than expected if the carriers the blocks are on have been migrated out to an allocator of a different type.

Defaults to all alloc_util allocators.

scheduler_ids - The scheduler ids whose allocator instances will be searched. A scheduler id of 0 will refer to the global instance that is not tied to any particular scheduler. Defaults to all schedulers and the global instance.

histogram_start - The upper bound of the first interval in the allocated block size histograms. Defaults to 128.

histogram_width - The number of intervals in the allocated block size histograms. Defaults to 18.

flags - Controls how to group the output, for example showing allocations on a per-process basis (when possible) rather than only a NIF/driver-basis. Defaults to [].

Example:

> instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
{ok,{128,0,
     #{udp_inet =>
           #{driver_event_state => {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}},
       system =>
           #{heap => {0,0,0,0,20,4,2,2,2,3,0,1,0,0,1},
             db_term => {271,3,1,52,80,1,0,0,0,0,0,0,0,0,0},
             code => {0,0,0,5,3,6,11,22,19,20,10,2,1,0,0},
             binary => {18,0,0,0,7,0,0,1,0,0,0,0,0,0,0},
             message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0},
             ... }
       spawn_forker =>
           #{driver_select_data_state =>
                 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
       ram_file_drv => #{drv_binary => {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}},
       prim_file =>
           #{process_specific_data => {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
             nif_trap_export_entry => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
             monitor_extended => {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
             drv_binary => {0,0,0,0,0,0,1,0,3,5,0,0,0,1,0},
             binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}},
       prim_buffer =>
           #{nif_internal => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
             binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}}

carriers()

(since OTP 21.0)

-spec carriers() -> {ok, Result} | {error, Reason}
                  when Result :: carrier_info_list(), Reason :: not_enabled.

Equivalent to carriers(#{}).

carriers(Options)

(since OTP 21.0)

-spec carriers(Options) -> {ok, Result} | {error, Reason}
                  when
                      Result :: carrier_info_list(),
                      Reason :: not_enabled,
                      Options ::
                          #{scheduler_ids => [non_neg_integer()],
                            allocator_types => [atom()],
                            histogram_start => pos_integer(),
                            histogram_width => pos_integer()}.

Returns a summary of all carriers in the system, optionally filtered by allocator type and scheduler id.

If the specified allocator types are not enabled, the call will fail with {error, not_enabled}.

The following options can be used:

allocator_types - The allocator types that will be searched. Defaults to all alloc_util allocators.

scheduler_ids - The scheduler ids whose allocator instances will be searched. A scheduler id of 0 will refer to the global instance that is not tied to any particular scheduler. Defaults to all schedulers and the global instance.

histogram_start - The upper bound of the first interval in the free block size histograms. Defaults to 512.

histogram_width - The number of intervals in the free block size histograms. Defaults to 14.

Example:

> instrument:carriers(#{ histogram_start => 512, histogram_width => 8 }).
{ok,{512,
     [{driver_alloc,false,262144,0,
                    [{driver_alloc,1,32784}],
                    {0,0,0,0,0,0,0,1}},
      {binary_alloc,false,32768,0,
                    [{binary_alloc,15,4304}],
                    {3,0,0,0,1,0,0,0}},
      {...}|...]}}

msacc

Convenience functions for microstate accounting

This module implements some convenience functions for analyzing microstate accounting data. For details about how to use the basic API and what the different states represent, see erlang:statistics(microstate_accounting).

Basic Scenario

1> msacc:start(1000).
ok
2> msacc:print().
Average thread real-time    : 1000513 us
Accumulated system run-time :    2213 us
Average scheduler run-time  :    1076 us

        Thread      aux check_io emulator       gc    other     port    sleep

Stats per thread:
     async( 0)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
     async( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
       aux( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%   99.99%
 scheduler( 1)    0.00%    0.03%    0.13%    0.00%    0.01%    0.00%   99.82%
 scheduler( 2)    0.00%    0.00%    0.00%    0.00%    0.03%    0.00%   99.97%

Stats per type:
         async    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
           aux    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%   99.99%
     scheduler    0.00%    0.02%    0.06%    0.00%    0.02%    0.00%   99.89%
ok

This first command enables microstate accounting for 1000 milliseconds. See start/0, stop/0, reset/0, and start/1 for more details. The second command prints the statistics gathered during that time. First three general statistics are printed.

Average real-time - The average time spent collecting data in the threads. This should be close to the time which data was collected.

System run-time - The total run-time of all threads in the system. This is what you get if you call msacc:stats(total_runtime,Stats).

Average scheduler run-time - The average run-time for the schedulers. This is the average amount of time the schedulers did not sleep.

Then one column per state is printed with a the percentage of time this thread spent in the state out of it's own real-time. After the thread specific time, the accumulated time for each type of thread is printed in a similar format.

Since we have the average real-time and the percentage spent in each state we can easily calculate the time spent in each state by multiplying Average thread real-time with Thread state %, that is, to get the time Scheduler 1 spent in the emulator state we do 1000513us * 0.13% = 1300us.

Summary

Types

msacc_data()

msacc_data_counters()

A map containing the different microstate accounting states and the number of microseconds spent in it.

msacc_data_thread()

msacc_id()

msacc_print_options()

The different options that can be given to print/2.

msacc_state()

The different states that a thread can be in. See erlang:statistics(microstate_accounting) for details.

msacc_stats()

msacc_stats_counters()

A map containing the different microstate accounting states. Each value in the map contains another map with the percentage of time that this thread has spent in the specific state. Both the percentage of system time and the time for that specific thread is part of the map.

msacc_stats_thread()

A map containing information about a specific thread. The percentages in the map can be either run-time or real-time depending on if runtime or realtime was requested from stats/2. system is the percentage of total system time for this specific thread.

msacc_type()

Functions

available()

This function checks whether microstate accounting is available or not.

from_file(Filename)

Read a file dump produced by to_file(Filename).

print()

Prints the current microstate accounting to standard out. Equivalent to msacc:print(msacc:stats(), #{}).

print(DataOrStats)

Equivalent to print(DataOrStats, #{}).

print(DataOrStats, Options)

Print the given microstate statistics values to standard out. With many states this can be verbose. See the top of this reference manual for a brief description of what the fields mean.

print(FileOrDevice, DataOrStats, Options)

Print the given microstate statistics values to the given file or device. The other arguments behave the same way as for print/2.

reset()

Reset microstate accounting counters. Returns whether is was enabled or disabled.

start()

Start microstate accounting. Returns whether it was previously enabled or disabled.

start(Time)

Resets all counters and then starts microstate accounting for the given milliseconds.

stats()

Returns a runtime system independent version of the microstate statistics data presented by erlang:statistics(microstate_accounting). All counters have been normalized to be in microsecond resolution.

stats/2

Returns the system time for the given microstate statistics values. System time is the accumulated time of all threads.

stop()

Stop microstate accounting. Returns whether is was previously enabled or disabled.

to_file(Filename)

Dumps the current microstate statistics counters to a file that can be parsed with file:consult/1.

Types

msacc_data()

(not exported) (since OTP 19.0)

-type msacc_data() :: [msacc_data_thread()].

msacc_data_counters()

(not exported) (since OTP 19.0)

-type msacc_data_counters() :: #{msacc_state() => non_neg_integer()}.

A map containing the different microstate accounting states and the number of microseconds spent in it.

msacc_data_thread()

(not exported) (since OTP 19.0)

-type msacc_data_thread() ::
          #{'$type' := msacc_data,
            type := msacc_type(),
            id := msacc_id(),
            counters := msacc_data_counters()}.

msacc_id()

(not exported) (since OTP 19.0)

-type msacc_id() :: non_neg_integer().

msacc_print_options()

(not exported) (since OTP 19.0)

-type msacc_print_options() :: #{system => boolean()}.

The different options that can be given to print/2.

msacc_state()

(not exported) (since OTP 19.0)

-type msacc_state() ::
          alloc | aux | bif | busy_wait | check_io | emulator | ets | gc | gc_fullsweep | nif | other |
          port | send | sleep | timers.

The different states that a thread can be in. See erlang:statistics(microstate_accounting) for details.

msacc_stats()

(not exported) (since OTP 19.0)

-type msacc_stats() :: [msacc_stats_thread()].

msacc_stats_counters()

(not exported) (since OTP 19.0)

-type msacc_stats_counters() :: #{msacc_state() => #{thread := float(), system := float()}}.

A map containing the different microstate accounting states. Each value in the map contains another map with the percentage of time that this thread has spent in the specific state. Both the percentage of system time and the time for that specific thread is part of the map.

msacc_stats_thread()

(not exported) (since OTP 19.0)

-type msacc_stats_thread() ::
          #{'$type' := msacc_stats,
            type := msacc_type(),
            id := msacc_id(),
            system := float(),
            counters := msacc_stats_counters()}.

A map containing information about a specific thread. The percentages in the map can be either run-time or real-time depending on if runtime or realtime was requested from stats/2. system is the percentage of total system time for this specific thread.

msacc_type()

(not exported) (since OTP 19.0)

-type msacc_type() :: aux | async | dirty_cpu_scheduler | dirty_io_scheduler | poll | scheduler.

Functions

available()

(since OTP 19.0)

-spec available() -> boolean().

This function checks whether microstate accounting is available or not.

from_file(Filename)

(since OTP 19.0)

-spec from_file(Filename) -> msacc_data() when Filename :: file:name_all().

Read a file dump produced by to_file(Filename).

print()

(since OTP 19.0)

-spec print() -> ok.

Prints the current microstate accounting to standard out. Equivalent to msacc:print(msacc:stats(), #{}).

print(DataOrStats)

(since OTP 19.0)

-spec print(DataOrStats) -> ok when DataOrStats :: msacc_data() | msacc_stats().

Equivalent to print(DataOrStats, #{}).

print(DataOrStats, Options)

(since OTP 19.0)

-spec print(DataOrStats, Options) -> ok
               when DataOrStats :: msacc_data() | msacc_stats(), Options :: msacc_print_options().

Print the given microstate statistics values to standard out. With many states this can be verbose. See the top of this reference manual for a brief description of what the fields mean.

It is possible to print more specific types of statistics by first manipulating the DataOrStats using stats/2. For instance if you want to print the percentage of run-time for each thread you can do:

msacc:print(msacc:stats(runtime, msacc:stats())).

If you want to only print run-time per thread type you can do:

msacc:print(msacc:stats(type, msacc:stats(runtime, msacc:stats()))).

Options

system - Print percentage of time spent in each state out of system time as well as thread time. Default: false.

print(FileOrDevice, DataOrStats, Options)

(since OTP 19.0)

-spec print(FileOrDevice, DataOrStats, Options) -> ok
               when
                   FileOrDevice :: file:filename() | io:device(),
                   DataOrStats :: msacc_data() | msacc_stats(),
                   Options :: msacc_print_options().

Print the given microstate statistics values to the given file or device. The other arguments behave the same way as for print/2.

reset()

(since OTP 19.0)

-spec reset() -> boolean().

Reset microstate accounting counters. Returns whether is was enabled or disabled.

start()

(since OTP 19.0)

-spec start() -> boolean().

Start microstate accounting. Returns whether it was previously enabled or disabled.

start(Time)

(since OTP 19.0)

-spec start(Time) -> true when Time :: timeout().

Resets all counters and then starts microstate accounting for the given milliseconds.

stats()

(since OTP 19.0)

-spec stats() -> msacc_data().

Returns a runtime system independent version of the microstate statistics data presented by erlang:statistics(microstate_accounting). All counters have been normalized to be in microsecond resolution.

stats/2

(since OTP 19.0)

-spec stats(Analysis, Stats) -> non_neg_integer()
               when Analysis :: system_realtime | system_runtime, Stats :: msacc_data();
           (Analysis, Stats) -> msacc_stats() when Analysis :: realtime | runtime, Stats :: msacc_data();
           (Analysis, StatsOrData) -> msacc_data() | msacc_stats()
               when Analysis :: type, StatsOrData :: msacc_data() | msacc_stats().

Returns the system time for the given microstate statistics values. System time is the accumulated time of all threads.

realtime - Returns all time recorded for all threads.

runtime - Returns all time spent doing work for all threads, i.e. all time not spent in the sleep state.

Returns fractions of real-time or run-time spent in the various threads from the given microstate statistics values.

Returns a list of microstate statistics values where the values for all threads of the same type has been merged.

stop()

(since OTP 19.0)

-spec stop() -> boolean().

Stop microstate accounting. Returns whether is was previously enabled or disabled.

to_file(Filename)

(since OTP 19.0)

-spec to_file(Filename) -> ok | {error, file:posix()} when Filename :: file:name_all().

Dumps the current microstate statistics counters to a file that can be parsed with file:consult/1.

scheduler

Measure scheduler utilization

This module contains utility functions for easy measurement and calculation of scheduler utilization. It act as a wrapper around the more primitive API erlang:statistics(scheduler_wall_time).

The simplest usage is to call the blocking scheduler:utilization(Seconds).

For non blocking and/or continuous calculation of scheduler utilization, the recommended usage is:

First call erlang:system_flag(scheduler_wall_time, true) to enable scheduler wall time measurements.

Call get_sample/0 to collect samples with some time in between.

Call utilization/2 to calculate the scheduler utilization in the interval between two samples.

When done call erlang:system_flag(scheduler_wall_time, false) to disable scheduler wall time measurements and avoid unecessary CPU overhead.

To get correct values from utilization/2, it is important that scheduler_wall_time is kept enabled during the entire interval between the two samples. To ensure this, the process that called erlang:system_flag(scheduler_wall_time, true) must be kept alive, as scheduler_wall_time will automatically be disabled if it terminates.

Summary

Types

sched_id()

sched_sample()

sched_type()

sched_util_result()

A list of tuples containing results for individual schedulers as well as aggregated averages. Util is the scheduler utilization as a floating point value between 0.0 and 1.0. Percent is the same utilization as a more human readable string expressed in percent.

Functions

get_sample()

Returns a scheduler utilization sample for normal and dirty-cpu schedulers. Returns undefined if system flag scheduler_wall_time has not been enabled.

get_sample_all()

Return a scheduler utilization sample for all schedulers, including dirty-io schedulers. Returns undefined if system flag scheduler_wall_time has not been enabled.

sample()

Return a scheduler utilization sample for normal and dirty-cpu schedulers. Will call erlang:system_flag(scheduler_wall_time, true) first if not already already enabled.

sample_all()

Return a scheduler utilization sample for all schedulers, including dirty-io schedulers. Will call erlang:system_flag(scheduler_wall_time, true) first if not already already enabled.

utilization/1

Measure utilization for normal and dirty-cpu schedulers during Seconds seconds, and then return the result.

utilization(Sample1, Sample2)

Calculates scheduler utilizations for the time interval between the two samples obtained from calling get_sample/0 or get_sample_all/0.

Types

sched_id()

(not exported) (since OTP 21.0)

-type sched_id() :: integer().

sched_sample()

(since OTP 21.0)

-opaque sched_sample()

sched_type()

(not exported) (since OTP 21.0)

-type sched_type() :: normal | cpu | io.

sched_util_result()

(not exported) (since OTP 21.0)

-type sched_util_result() ::
          [{sched_type(), sched_id(), float(), string()} |
           {total, float(), string()} |
           {weighted, float(), string()}].

A list of tuples containing results for individual schedulers as well as aggregated averages. Util is the scheduler utilization as a floating point value between 0.0 and 1.0. Percent is the same utilization as a more human readable string expressed in percent.

{normal, SchedulerId, Util, Percent} - Scheduler utilization of a normal scheduler with number SchedulerId. Schedulers that are not online will also be included. Online schedulers have the lowest SchedulerId.

{cpu, SchedulerId, Util, Percent} - Scheduler utilization of a dirty-cpu scheduler with number SchedulerId.

{io, SchedulerId, Util, Percent} - Scheduler utilization of a dirty-io scheduler with number SchedulerId. This tuple will only exist if both samples were taken with sample_all/0.

{total, Util, Percent} - Total utilization of all normal and dirty-cpu schedulers.

{weighted, Util, Percent} - Total utilization of all normal and dirty-cpu schedulers, weighted against maximum amount of available CPU time.

Functions

get_sample()

(since OTP 24.3)

-spec get_sample() -> sched_sample() | undefined.

Returns a scheduler utilization sample for normal and dirty-cpu schedulers. Returns undefined if system flag scheduler_wall_time has not been enabled.

get_sample_all()

(since OTP 24.3)

-spec get_sample_all() -> sched_sample() | undefined.

Return a scheduler utilization sample for all schedulers, including dirty-io schedulers. Returns undefined if system flag scheduler_wall_time has not been enabled.

sample()

(since OTP 21.0)

-spec sample() -> sched_sample().

Return a scheduler utilization sample for normal and dirty-cpu schedulers. Will call erlang:system_flag(scheduler_wall_time, true) first if not already already enabled.

Note

This function is not recommended as there is no way to detect if scheduler_wall_time already was enabled or not. If scheduler_wall_time has been disabled between two samples, passing them to utilization/2 will yield invalid results.

Instead use get_sample/0 together with erlang:system_flag(scheduler_wall_time, _).

sample_all()

(since OTP 21.0)

-spec sample_all() -> sched_sample().

Return a scheduler utilization sample for all schedulers, including dirty-io schedulers. Will call erlang:system_flag(scheduler_wall_time, true) first if not already already enabled.

Note

This function is not recommended for same reason as sample/0. Instead use get_sample_all/0 together with erlang:system_flag(scheduler_wall_time,_).

utilization/1

(since OTP 21.0)

-spec utilization(Seconds) -> sched_util_result() when Seconds :: pos_integer();
                 (Sample) -> sched_util_result() when Sample :: sched_sample().

Measure utilization for normal and dirty-cpu schedulers during Seconds seconds, and then return the result.

Will automatically first enable and then disable scheduler_wall_time.

Calculate scheduler utilizations for the time interval from when Sample was taken and "now". The same as calling scheduler:utilization(Sample, scheduler:sample_all()).

Note

This function is not recommended as it's so easy to get invalid results without noticing. In particular do not do this:

scheduler:utilization(scheduler:sample()). % DO NOT DO THIS!

The above example takes two samples in rapid succession and calculates the scheduler utilization between them. The resulting values will probably be more misleading than informative.

Instead use scheduler:utilization/2 and call get_sample/0 to get samples with some time in between.

utilization(Sample1, Sample2)

(since OTP 21.0)

-spec utilization(Sample1, Sample2) -> sched_util_result()
                     when Sample1 :: sched_sample(), Sample2 :: sched_sample().

Calculates scheduler utilizations for the time interval between the two samples obtained from calling get_sample/0 or get_sample_all/0.

This function itself, does not need scheduler_wall_time to be enabled. However, for a correct result, scheduler_wall_time must have been enabled during the entire interval between the two samples.

system_information

System Information

Summary

Functions

sanity_check()

Performs a sanity check on the system.

to_file(FileName)

Writes miscellaneous system information to file. This information will typically be requested by the Erlang/OTP team at Ericsson AB when reporting an issue.

Functions

sanity_check()

(since OTP 17.0)

-spec sanity_check() -> ok | {failed, Failures}
                      when
                          Application :: atom(),
                          ApplicationVersion :: string(),
                          MissingRuntimeDependencies ::
                              {missing_runtime_dependencies, ApplicationVersion, [ApplicationVersion]},
                          InvalidApplicationVersion :: {invalid_application_version, ApplicationVersion},
                          InvalidAppFile :: {invalid_app_file, Application},
                          Failure ::
                              MissingRuntimeDependencies | InvalidApplicationVersion | InvalidAppFile,
                          Failures :: [Failure].

Performs a sanity check on the system.

If no issues were found, ok is returned. If issues were found, {failed, Failures} is returned. All failures found will be part of the Failures list. Currently defined Failure elements in the Failures list:

InvalidAppFile - An application has an invalid .app file. The second element identifies the application which has the invalid .app file.

InvalidApplicationVersion - An application has an invalid application version. The second element identifies the application version that is invalid.

MissingRuntimeDependencies - An application is missing runtime dependencies. The second element identifies the application (with version) that has missing dependencies. The third element contains the missing dependencies.

Note that this check use application versions that are loaded, or will be loaded when used. You might have application versions that satisfies all dependencies installed in the system, but if those are not loaded this check will fail. Of course, the system will also fail when used like this. This can happen when you have multiple branched versions of the same application installed in the system, but there does not exist a boot script identifying the correct application version.

Currently the sanity check is limited to verifying runtime dependencies found in the .app files of all applications. More checks will be introduced in the future. This implies that the return type will change in the future.

Note

An ok return value only means that sanity_check/0 did not find any issues, not that no issues exist.

to_file(FileName)

(since OTP 17.0)

-spec to_file(FileName) -> ok | {error, Reason}
                 when
                     FileName :: file:name_all(),
                     Reason :: file:posix() | badarg | terminated | system_limit.

Writes miscellaneous system information to file. This information will typically be requested by the Erlang/OTP team at Ericsson AB when reporting an issue.