查看源码 dbg (runtime_tools v2.1.1)

基于文本的跟踪工具

该模块实现了 trace:process/4trace:port/4trace:function/4 BIF 的基于文本的接口,简化了对函数、进程、端口和消息的跟踪。

要快速开始跟踪函数调用,可以在 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]

这些实用程序也适用于在大型系统上进行系统测试,在这些系统中,其他工具对系统性能的影响过于严重。还包括一些对顺序跟踪的原始支持;请参阅高级主题部分。

从 shell 进行简单的跟踪,无需事先设置

要以最少的麻烦跟踪对函数的调用,请调用 dbg:c(Module, Name, Arguments)dbg:c/3 启动一个临时的跟踪接收器,启用所有跟踪标志,并从临时进程调用指定的函数。例如,以下是如何跟踪对 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"}]

生成四个跟踪事件

  • 一个发送事件 (!),表示从当前进程向 application_controller 进程发送请求。
  • 当当前进程在 receive 中等待回复到达时,发生一个调度出事件 (out)。
  • 当回复到达时,当前进程被调度进来时,发生一个调度入事件 (in)。
  • 当当前进程从 application_controller 进程检索回复时,会发生一个 receive 事件 (<<)。

dbg:c/4 函数有一个用于指定跟踪标志的第四个参数。以下是如何仅显示消息发送和接收

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

从 shell 进行跟踪

从 shell 进行跟踪的另一种方法是显式启动一个跟踪器并在您要跟踪的进程上设置您选择的跟踪标志。例如,以下是如何跟踪消息和进程事件

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

为了跟踪函数调用,除了为进程启用 call 跟踪标志外,还需要为要跟踪的函数设置跟踪模式

示例

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

高级主题 - 与 seq_trace 结合使用

dbg 模块主要针对通过 trace:process/4 函数进行跟踪。有时希望以更精细的方式跟踪消息,这可以在 seq_trace 模块的帮助下完成。

seq_trace 实现顺序跟踪(在 AXE10 世界中称为“forlopp 跟踪”)。dbg 可以解释从 seq_trace 生成的消息,并且可以使用相同类型的跟踪的跟踪器函数。seq_trace 消息也可以发送到跟踪端口以进行进一步分析。

由于匹配规范可以启用顺序跟踪,因此 dbgseq_trace 的组合可能非常强大。这个简短的示例显示了一个会话,其中使用顺序跟踪来跟踪 dbg 模块和跟踪本身

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}

此会话将 system_tracer 设置为与普通跟踪器进程相同的进程(即 <0.31.0>),并将函数 dbg:get_tracer 的跟踪模式设置为具有设置顺序令牌的操作的模式。当跟踪进程调用该函数时(在本例中跟踪所有进程),该进程会被令牌“污染”,并且 seq_trace 消息会同时发送给服务器请求和响应。seq_trace:set_token([]) 在调用后会清除 seq_trace 令牌,这就是为什么当答案通过 shell 传播到控制台端口时不会发送任何消息的原因。否则输出会更嘈杂。

注意

在组长进程(I/O 进程)上跟踪函数调用时,存在导致死锁的风险。如果组长进程生成一个跟踪消息,并且跟踪器进程通过调用跟踪处理函数向同一组长发送 I/O 请求,则会发生这种情况。仅当跟踪处理程序使用 io 函数(如 format/2)打印到 tty 时,才会出现此问题。请注意,当调用 dbg:p(all, call) 时,也会跟踪 IO 进程。这是一个例子

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

这是另一个例子

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

我们在第一个示例中发生死锁的原因是,当按下 TAB 键展开函数名时,组长(处理字符输入)会调用 mymod:module_info()。这将生成一个跟踪消息,从而导致跟踪器进程通过调用 io:format/2 向组长发送 I/O 请求。我们最终陷入死锁。

在第二个示例中,我们使用默认的跟踪处理程序函数。此处理程序通过向 user 进程发送 IO 请求来打印到 tty。当 Erlang 在 oldshell 模式下启动时,shell 进程将以 user 作为其组长,并且在本示例中跟踪器进程也会以 user 作为其组长。由于 user 调用 lists 中的函数,因此一旦发送第一个 IO 请求,我们就会陷入死锁。

以下是避免死锁的一些建议

  • 不要跟踪跟踪器进程的组长。如果已为所有进程打开跟踪,请调用 dbg:p(TracerGLPid, clear) 以停止跟踪组长 (TracerGLPid)。process_info(TracerPid, group_leader) 会告诉您这是哪个进程 (TracerPid 是从 dbg:get_tracer/0 返回的)。
  • 如果使用默认的跟踪处理程序函数,则不要跟踪 user 进程。
  • 在您自己的跟踪处理程序函数中,调用 erlang:display/1 而不是 io 函数,或者,如果 user 不用作组长,则打印到 user 而不是默认的组长。示例:io:format(user, Str, Args)

摘要

函数

使用设置的 Flags 中的跟踪标志评估表达式 apply(Mod, Fun, Args)

从已跟踪节点的列表中清除节点。

禁用由 ModuleOrMFA 指定的一个或多个函数的调用跟踪。

清除指定跟踪事件(send'receive')的匹配规范,恢复为跟踪所有触发事件的默认值。

禁用由 ModuleOrMFA 指定的一个或多个函数的全局调用跟踪。

禁用由 ModuleOrMFA 指定的一个或多个函数的局部调用跟踪。

忘记在调用 tp/2 期间保存的所有匹配规范。

忘记在调用 tp/2 期间保存的特定匹配规范。

伪函数,通过解析转换将函数调用中键入为参数的文字 fun 转换为匹配规范

返回所有跟踪消息发送到的进程、端口或跟踪器模块。

h()

提供简短在线帮助的项列表。

提供 dbg 模块中函数的简短帮助文本。

i()

显示有关所有已跟踪进程和端口的信息。

在控制台上显示已跟踪节点的列表。

列出之前在会话中使用的所有匹配规范。

将远程节点(节点名)添加到执行跟踪的节点列表中。

等同于 p(项目, [m])

根据 标志 指定的值跟踪 项目

从文本文件中读取匹配规范,该文件可能由 wtp/1 函数生成。

使用提供的会话运行 dbg 命令,如果提供会话名称,则在调用期间创建会话。

使用给定的 名称 创建一个新的 dbg 会话。

销毁一个 dbg session/0

停止 dbg 服务器,清除所有进程的所有跟踪标志,清除所有函数的跟踪模式,清除发送/接收的跟踪模式,关闭所有跟踪客户端,并关闭所有跟踪端口。

关闭先前启动的跟踪客户端。

为一个或多个由 模块或MFA 指定的导出函数启用调用跟踪。

将匹配规范与跟踪事件 send'receive' 相关联。

为一个或多个由 模块或MFA 指定的函数启用调用跟踪。

启动一个跟踪客户端,该客户端读取由跟踪端口驱动程序创建的输出(请参阅 trace_port/2),并以与 tracer/0 函数创建的跟踪器进程大致相同的方式处理它。

此函数的工作方式与 trace_client/2 完全相同,但允许您编写自己的处理程序函数。

创建一个生成跟踪端口的 fun,它适合作为 tracer/2 的第二个参数。

此函数用于对给定节点(节点名)上的活动跟踪端口驱动程序执行控制操作。

在本地节点上启动一个服务器,该服务器将接收所有跟踪消息。

在本地节点上启动具有附加参数的跟踪器服务器。

此函数等同于 tracer/2,但在给定节点上运行。

将会话期间保存的所有匹配规范(通过调用 tp/2tpl/2)以及内置匹配规范,保存在名称由 名称 指定的文本文件中。

类型

链接到此类型

built_in_alias()

查看源代码 (未导出)
-type built_in_alias() :: x | c | cx.
链接到此类型

handler_spec()

查看源代码 (未导出)
-type handler_spec() ::
          {HandlerFun :: fun((Event :: term(), Data :: term()) -> NewData :: term()),
           InitialData :: term()}.
链接到此类型

match_desc()

查看源代码 (未导出)
-type match_desc() :: [match_info()].
链接到此类型

match_info()

查看源代码 (未导出)
-type match_info() :: {saved, tp_id()} | match_num().
链接到此类型

match_num()

查看源代码 (未导出)
-type match_num() :: {matched, node(), integer()} | {matched, node(), 0, RPCError :: term()}.
链接到此类型

match_pattern()

查看源代码 (未导出)
-type match_pattern() :: atom() | list().
-type match_spec() :: [{match_pattern(), [_], [_]}].
-opaque session()

一个 dbg 会话,可以由 session/2 用于创建隔离的调试会话。

链接到此类型

tp_arity()

查看源代码 (未导出)
-type tp_arity() :: arity() | '_'.
链接到此类型

tp_function()

查看源代码 (未导出)
-type tp_function() :: atom() | '_'.
-type tp_id() :: pos_integer().
链接到此类型

tp_match_spec()

查看源代码 (未导出)
-type tp_match_spec() :: tp_id() | built_in_alias() | [] | match_spec().
链接到此类型

tp_module()

查看源代码 (未导出)
-type tp_module() :: module() | '_'.
链接到此类型

trace_wrap_file_size()

查看源代码 (未导出)
-type trace_wrap_file_size() :: non_neg_integer() | {time, WrapTime :: pos_integer()}.
链接到此类型

trace_wrap_files_spec()

查看源代码 (未导出)
-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()}.

函数

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

等效于 c(Mod, Fun, Args, all)

链接到此函数

c(Mod, Fun, Args, Flags)

查看源代码
-spec c(Mod :: module(), Fun :: atom(), Args :: [term()], Flags :: term()) -> term().

使用设置的 Flags 中的跟踪标志评估表达式 apply(Mod, Fun, Args)

c 代表 call(调用)。

这是从 Erlang shell 跟踪进程的便捷方法。

-spec cn(Nodename) -> ok when Nodename :: node().

从已跟踪节点的列表中清除节点。

cn 代表 clear node(清除节点)。

后续对 tp/2p/2 的调用将不会考虑该节点,但已在该节点上激活的跟踪将继续生效。

返回 ok。此调用不会失败。

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

等效于 ctp({'_', '_', '_'})

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

禁用由 ModuleOrMFA 指定的一个或多个函数的调用跟踪。

如果 模块或MFA 是原子(模块名称),则此函数调用等同于 ctp({模块或MFA, '_', '_'})

否则,模块或MFA 应该为 {模块, 函数, 参数个数}

ctp 代表 clear trace pattern(清除跟踪模式)。

模块或MFA 的语义与 tp/2tpl/2 中相应的函数规范相同。本地和全局调用跟踪均被禁用。

返回值反映了匹配的函数数量,并按照 tp/2 中的描述构建,但不会返回 {saved, N} 元组。

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

等效于 ctp({Module, Function, '_'})

链接到此函数

ctp(Module, Function, Arity)

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

等效于 ctp({Module, Function, Arity})

链接到此函数

ctpe(Event)

查看源代码 (自 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()}.

清除指定跟踪事件(send'receive')的匹配规范,恢复为跟踪所有触发事件的默认值。

ctpe 代表 clear trace pattern event(清除跟踪模式事件)。

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

等效于 ctpg({'_', '_', '_'})

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

禁用由 ModuleOrMFA 指定的一个或多个函数的全局调用跟踪。

如果 模块或MFA 是原子(模块名称),则此函数调用等同于 ctpg({模块或MFA, '_', '_'})

否则,模块或MFA 应该为 {模块, 函数, 参数个数}

ctpg 代表 clear trace pattern global(清除跟踪模式全局)。

此函数的工作方式与 ctp/1 相同,但仅禁用使用 tp/2 设置的跟踪(不使用 tpl/2)。

链接到此函数

ctpg(Module, Function)

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

等效于 ctpg({Module, Function, '_'})

链接到此函数

ctpg(Module, Function, Arity)

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

等效于 ctpg({Module, Function, Arity})

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

等效于 ctpl({'_', '_', '_'})

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

禁用由 ModuleOrMFA 指定的一个或多个函数的局部调用跟踪。

如果 模块或MFA 是原子(模块名称),则此函数调用等同于 ctpl({模块或MFA, '_', '_'})

否则,模块或MFA 应该为 {模块, 函数, 参数个数}

ctpl 代表 clear trace pattern local(清除跟踪模式本地)。

此函数的工作方式与 ctp/1 相同,但仅禁用使用 tpl/2 设置的跟踪(不使用 tp/2)。

链接到此函数

ctpl(Module, Function)

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

等效于 ctpl({Module, Function, '_'})

链接到此函数

ctpl(Module, Function, Arity)

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

等效于 ctpl({Module, Function, Arity})

-spec dtp() -> ok.

忘记在调用 tp/2 期间保存的所有匹配规范。

dtp 代表 delete trace patterns(删除跟踪模式)。

在从使用 rtp/1 的文件恢复其他匹配规范之前,删除所有已保存的匹配规范很有用。使用 dtp/1 删除特定的已保存匹配规范。

-spec dtp(N) -> ok when N :: tp_id().

忘记在调用 tp/2 期间保存的特定匹配规范。

dtp 代表 delete trace pattern(删除跟踪模式)。

-spec flush_trace_port() -> term().

等效于 flush_trace_port(node())

链接到此函数

flush_trace_port(Nodename)

查看源代码
-spec flush_trace_port(Nodename :: node()) -> ok | {error, Reason :: term()}.

等效于 trace_port_control(Nodename, flush)

-spec fun2ms(LiteralFun) -> MatchSpec
                when LiteralFun :: fun((term()) -> term()), MatchSpec :: match_spec().

伪函数,通过解析转换将函数调用中键入为参数的文字 fun 转换为匹配规范

“字面量”的含义是,fun 需要以文本形式编写为函数调用的参数;它不能保存在变量中,然后将该变量传递给函数。此外,必须启用解析转换模块 ms_transform。启用它的最简单方法是将以下行添加到源文件中

-include_lib("stdlib/include/ms_transform.hrl").

如果未在源文件中包含 ms_transform.hrl,则会导致运行时错误,而不是编译时错误。

也可以直接从 Erlang shell 调用此函数,如以下示例所示。

fun 的头部必须是一个匹配列表的单个模式。该模式将用于匹配调用的参数

示例:

1> dbg:fun2ms(fun([_,_]) -> true end).
[{['_','_'],[],[true]}]
2> dbg:fun2ms(fun(Args) when length(Args) > 6 -> true end).
[{'$1',[{'>',{length,'$1'},6}],[true]}]

第一个匹配规范在调用具有两个参数的函数时匹配。第二个匹配当调用具有 6 个以上参数的函数时匹配。

示例:

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}

前面的两个示例显示了当 fun 无法转换为匹配规范时会发生什么。在第一个示例中,fun 的头部不可能匹配列表。在第二个示例中,尝试使用位语法分解二进制文件,而匹配规范中当前不支持该语法。

但是,请注意,可以匹配字面量二进制文件

1> dbg:fun2ms(fun([<<"abc">>]) -> true end).
[{[<<"abc">>],[],[true]}]

匹配规范支持 Erlang 支持的 保护表达式 的很大一部分子集,但不是全部。例如,当前不支持更新映射

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}

但是,允许在保护中创建映射

1> dbg:fun2ms(fun([M]) when map_size(#{a => b}) > 2 -> true end).
[{['$1'],[{'>',{map_size,#{a => b}},2}],[true]}]

可以导入环境中的变量,因此这可行

1> X = 3.
3
2> dbg:fun2ms(fun([M,N]) when N > X  -> return_trace() end).
[{['$1','$2'],[{'>','$2',{const,3}}],[{return_trace}]}]

导入的变量将被替换为 const 表达式,这与 Erlang fun 的静态作用域一致。

在 fun 的主体中,只允许保护表达式和对 仅允许用于跟踪的特殊函数 的调用。

示例:

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}

警告

如果不对调用 dbg:fun2ms/1 的模块应用解析转换,则该调用将在运行时失败,并出现 badarg 异常。

更多信息可在 STDLIB 中模块 ms_transform 的文档中找到。

-spec get_tracer() -> term().

等效于 get_tracer(node())

-spec get_tracer(Nodename) -> {ok, Tracer}
                    when Nodename :: atom(), Tracer :: port() | pid() | {module(), term()}.

返回所有跟踪消息发送到的进程、端口或跟踪器模块。

-spec h() -> ok.

提供简短在线帮助的项列表。

h 代表 help(帮助)。

-spec h(Item) -> ok when Item :: atom().

提供 dbg 模块中函数的简短帮助文本。

h 代表 help(帮助)。

可以通过调用 dbg:h/0 列出可用的项。

-spec i() -> ok.

显示有关所有已跟踪进程和端口的信息。

i 代表 information(信息)。

-spec ln() -> ok.

在控制台上显示已跟踪节点的列表。

ln 代表 list nodes(列出节点)。

-spec ltp() -> ok.

列出之前在会话中使用的所有匹配规范。

ltp 代表 list trace patterns(列出跟踪模式)。

此函数列出先前在调用 tp/2tpl/2 期间保存的所有匹配规范,以及所有内置匹配规范。这避免了重新键入复杂的匹配规范。请注意,如果调用 stop/0,则匹配规范将会丢失。

匹配规范可以保存在文件中(如果存在读写文件系统),以便在以后的调试会话中使用;请参阅 wtp/1rtp/1

有三种内置跟踪模式

  • exception_trace, x - 设置一个跟踪,它将显示函数名称、参数、返回值以及从函数引发的异常

  • caller_trace, c - 设置一个跟踪,它显示函数名称、参数以及有关哪个函数调用它的信息

  • caller_exception_trace, cx - 结合了 exception_tracecaller_trace

这是一个示例,展示如何使用内置匹配规范

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]
-spec n(Nodename) -> {ok, Nodename} | {error, Reason} when Nodename :: node(), Reason :: term().

将远程节点(节点名)添加到执行跟踪的节点列表中。

n 代表 node(节点)。

dbg 服务器维护一个列表,其中包含应执行跟踪的节点。每当调用 tp/2p/2 时,它都会在此列表中的所有节点上执行,包括本地节点(除了使用特定 pid/0port/0 作为第一个参数的 p/2,在这种情况下,该命令仅在指定进程或端口所在的节点上执行)。

调用此函数时,它会在远程节点上启动一个跟踪器进程,该进程会将所有跟踪消息发送到本地节点上的跟踪器进程(通过 Erlang 分布)。如果本地节点上没有运行跟踪器进程,则会返回错误原因 no_local_tracer。本地节点上的跟踪器进程必须使用 tracer/0,2 函数启动。

如果 Nodename 是本地节点,则会返回错误原因 cant_add_local_node

如果本地节点上正在运行跟踪端口(请参阅 trace_port/2),则无法使用跟踪器进程跟踪远程节点。会返回错误原因 cant_trace_remote_pid_to_local_port。但是,可以使用 tracer/3 函数在远程节点上启动跟踪端口。

如果节点 Nodename 不可达,该函数也会返回错误。

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

等同于 p(项目, [m])

-spec p(Item :: term(), Flags :: term()) -> {ok, MatchDesc} | {error, term()}
           when
               MatchDesc :: [MatchNum],
               MatchNum :: {matched, node(), integer()} | {matched, node(), 0, RPCError},
               RPCError :: term().

根据 标志 指定的值跟踪 项目

p 代表 process(进程)。

以下类型的值允许用于 Item

  • pid/0port/0 - 跟踪相应的进程或端口。该进程或端口可以是远程进程或端口(在另一个 Erlang 节点上)。该节点必须在跟踪节点列表中(请参阅 n/1tracer/3)。

  • all - 将跟踪系统中的所有进程和端口以及之后创建的所有进程和端口。

  • processes - 将跟踪系统中的所有进程以及之后创建的所有进程。

  • ports - 将跟踪系统中的所有端口以及之后创建的所有端口。

  • new - 将跟踪调用后创建的所有进程和端口。

  • new_processes - 将跟踪调用后创建的所有进程。

  • new_ports - 将跟踪调用后创建的所有端口。

  • existing - 将跟踪所有现有进程和端口。

  • existing_processes - 将跟踪所有现有进程。

  • existing_ports - 将跟踪所有现有端口。

  • atom/0 - 将跟踪具有相应注册名称的进程或端口。该进程或端口可以在另一个 Erlang 节点上。该节点必须在跟踪节点列表中(请参阅 n/1tracer/3)。

  • integer/0 - 跟踪进程 <0.Item.0>

  • {X, Y, Z} - 跟踪进程 <X.Y.Z>

  • string/0 - 如果 Item 是一个字符串 "<X.Y.Z>",如从 pid_to_list/1 返回的,则跟踪进程 <X.Y.Z>

当启用表示一组进程的 Item 时,将在使用 n/1tracer/3 函数添加的所有节点上启用该 Item

Flags 可以是单个原子或标志列表。可用的标志有:

  • s (send) - 跟踪进程或端口发送的消息。

  • r (receive) - 跟踪进程或端口接收的消息。

  • m (messages) - 跟踪进程或端口接收和发送的消息。

  • c (call) - 根据系统中设置的跟踪模式跟踪进程的全局函数调用(请参阅 tp/2)。

  • p (procs) - 跟踪与该进程相关的事件。

  • ports - 跟踪与该端口相关的事件。

  • sos (set on spawn) - 使被跟踪进程创建的所有进程继承被跟踪进程的跟踪标志。

  • sol (set on link) - 每当被跟踪进程链接到 P2 时,使另一个进程 P2 继承被跟踪进程的跟踪标志。

  • sofs (set on first spawn) - 这与 sos 相同,但仅适用于被跟踪进程生成的第一个进程。

  • sofl (set on first link) - 这与 sol 相同,但仅适用于被跟踪进程对 link/1 的第一次调用。

  • all - 设置除 silent 之外的所有标志。

  • clear - 清除所有标志。

该列表还可以包含 trace:process/4trace:port/4 中允许的任何标志。

此函数返回一个错误元组或一个 {ok, List} 元组。List 包含有关匹配的进程和端口数量的规范(在单个 pid 的情况下,恰好为 1)。匹配的进程的规范是 {matched, Node, N}。如果使用 rpc 对远程节点的远程处理器调用失败,则 rpc 错误消息将作为元组中的第四个元素返回,并且匹配的进程数为 0。

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

从文本文件中读取匹配规范,该文件可能由 wtp/1 函数生成。

rtp 代表 read trace patterns(读取跟踪模式)。

该函数验证所有匹配规范的语法是否正确。如果在任何匹配规范中发现任何错误,则不会将任何匹配规范添加到正在运行的系统的已保存匹配规范列表中。

文件中的匹配规范与当前的匹配规范合并,这样就不会生成重复项。使用 ltp/0 来查看为文件中的规范分配了哪些编号。

该函数将返回一个错误元组,可能是由于 I/O 问题(例如,文件不存在或不可读)或由于文件格式问题。在后一种情况下,Reason 是一种或多或少文本格式的,提示导致问题的原因。

链接到此函数

session(会话, Fun)

查看源代码 (自 OTP 27.0 起)
-spec session(atom(), fun(() -> term())) -> term();
             (session(), fun(() -> term())) -> term().

使用提供的会话运行 dbg 命令,如果提供会话名称,则在调用期间创建会话。

使用提供的 fun 调用的任何 dbg 函数将使用提供的 session/0 而不是默认的 dbg 会话。这意味着跟踪将与系统上的其他跟踪用户隔离。

该函数返回 fun 返回的项。

示例:

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

session/0 的状态在 session/2 调用之间保留,因此您可以在调试应用程序时多次调用 session/2

示例:

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

注意

会话功能在 Erlang/OTP 27 中是实验性的,并且可能会在未来的版本中更改,恕不另行通知。

链接到此函数

session_create(名称)

查看源代码 (自 OTP 27.0 起)
-spec session_create(atom()) -> session().

使用给定的 名称 创建一个新的 dbg 会话。

会话与调用进程链接,并且将

多个会话可以具有相同的名称。

注意

会话功能在 Erlang/OTP 27 中是实验性的,并且可能会在未来的版本中更改,恕不另行通知。

链接到此函数

session_destroy(会话)

查看源代码 (自 OTP 27.0 起)
-spec session_destroy(Session :: session()) -> ok.

销毁一个 dbg session/0

这将终止所有已启动的进程并销毁 trace:session/0

-spec stop() -> ok.

停止 dbg 服务器,清除所有进程的所有跟踪标志,清除所有函数的跟踪模式,清除发送/接收的跟踪模式,关闭所有跟踪客户端,并关闭所有跟踪端口。

链接到此函数

stop_trace_client(进程ID)

查看源代码
-spec stop_trace_client(Pid) -> ok when Pid :: pid().

关闭先前启动的跟踪客户端。

Pid 参数是从 trace_client/2trace_client/3 调用返回的进程 ID。

链接到此函数

tp(模块或MFA, 匹配规范)

查看源代码
-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().

为一个或多个由 模块或MFA 指定的导出函数启用调用跟踪。

如果 ModuleOrMFA 是一个原子(模块名称),则此函数调用等效于 tp({ModuleOrMFA, '_', '_'}, MatchSpec)

否则,模块或MFA 应该为 {模块, 函数, 参数个数}

tp 代表 trace pattern(跟踪模式)。

所有导出的函数,只要与 {Module, Function, Arity} 参数匹配,都会被考虑在内,但匹配规范可能会进一步缩小生成跟踪消息的函数调用集合。

有关 MatchSpec 参数格式的描述,请参阅Erlang 中的匹配规范,其中解释了通用的匹配规范语言。最常用的通用匹配规范可以作为内置别名找到;有关详细信息,请参见下文的 ltp/0

元组的 Module、Function 和/或 Arity 部分可以指定为原子 '_',这是一个匹配所有模块、函数或参数数量的通配符。请注意,如果 Module 被指定为 '_',则 FunctionArity 部分也必须指定为 '_'。对于 FunctionArity 的关系,情况也是如此。

所有通过 n/1tracer/3 添加的节点都将受此调用影响,如果 Module 不是 '_',则该模块将在所有节点上加载。

该函数返回一个错误元组或一个 {ok, List} 元组。 List 包含匹配的函数数量的规范,其表示方式与 p/2 的返回值中进程和端口的表示方式相同。

如果 MatchSpec 不是 [],则返回值中可能存在一个元组 {saved, N}。整数 N 随后可以在对此函数的调用中用作给定表达式的“别名”。

如果匹配规范无效,则返回 {error, Errors} 元组。 Errors 是元组列表 {error, string()},其中字符串是对编译错误的文本解释。例如

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(模块, 函数, 匹配规范)

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

等同于 tp({模块, 函数, '_'}, 匹配规范)

链接到此函数

tp(模块, 函数, 参数个数, 匹配规范)

查看源代码
-spec tp(Module :: tp_module(),
         Function :: tp_function(),
         Arity :: tp_arity(),
         MatchSpec :: tp_match_spec()) ->
            {ok, match_desc()} | {error, term()}.

等同于 tp({模块, 函数, 参数个数}, 匹配规范)

链接到此函数

tpe(事件, 匹配规范)

查看源代码 (自 OTP 19.0 起)
-spec tpe(Event, MatchSpec) -> {ok, MatchDesc :: match_desc()} | {error, term()}
             when Event :: send | 'receive', MatchSpec :: tp_match_spec().

将匹配规范与跟踪事件 send'receive' 相关联。

tpe 代表 trace pattern event(跟踪模式事件)。

默认情况下,如果为进程启用了所有执行的 send'receive' 事件都会被跟踪。可以使用匹配规范来根据发送者、接收者和/或消息内容过滤跟踪的事件。

有关 MatchSpec 参数格式的描述,请参阅Erlang 中的匹配规范,其中解释了通用的匹配规范语言。

对于 send,匹配是在列表 [Receiver, Msg] 上完成的。 Receiver 是接收者的进程或端口标识,Msg 是消息项。可以使用保护函数 self/0 访问发送进程的 pid。

对于 'receive',匹配是在列表 [Node, Sender, Msg] 上完成的。 Node 是发送者的节点名称。Sender 是发送者的进程或端口标识,如果发送者未知(远程发送者可能就是这种情况),则为原子 undefinedMsg 是消息项。可以通过调用 self/0 来访问接收进程的 pid。

所有通过 n/1tracer/3 添加的节点都将受此调用影响。

返回值与 tp/2 的相同。匹配的事件数始终为 1,因为 tpe/2 不接受任何形式的通配符作为参数 Event

链接到此函数

tpl({模块, 函数, 参数个数}, 匹配规范)

查看源代码
-spec tpl(Module | {Module, Function :: tp_function(), Arity :: tp_arity()},
          MatchSpec :: tp_match_spec()) ->
             {ok, MatchDesc :: term()} | {error, term()}
             when Module :: tp_module().

为一个或多个由 模块或MFA 指定的函数启用调用跟踪。

如果 ModuleOrMFA 是一个原子(模块名称),则此函数调用等效于 tpl({ModuleOrMFA, '_', '_'}, MatchSpec)

否则,模块或MFA 应该为 {模块, 函数, 参数个数}

tpl 代表 trace pattern local(本地跟踪模式)。

此函数与 tp/2 的工作方式相同,但启用对本地和导出函数的本地或远程调用的跟踪。

链接到此函数

tpl(模块, 函数, 匹配规范)

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

等同于 tpl({模块, 函数, '_'}, 匹配规范)

链接到此函数

tpl(模块, 函数, 参数个数, 匹配规范)

查看源代码
-spec tpl(Module :: tp_module(),
          Function :: tp_function(),
          Arity :: tp_arity(),
          MatchSpec :: tp_match_spec()) ->
             {ok, match_desc()} | {error, term()}.

等同于 tpl({模块, 函数, 参数个数}, 匹配规范)

链接到此函数

trace_client(类型, 参数)

查看源代码
-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().

启动一个跟踪客户端,该客户端读取由跟踪端口驱动程序创建的输出(请参阅 trace_port/2),并以与 tracer/0 函数创建的跟踪器进程大致相同的方式处理它。

如果 Typefile,则客户端读取存储在名为 Filename 的文件或由 WrapFilesSpec 指定的文件中的所有跟踪消息(必须与创建跟踪时使用的相同),并让默认处理程序函数在控制台上格式化消息。这是解释文件跟踪端口驱动程序存储在文件中的数据的一种方法。

如果 Typefollow_file,则客户端的行为与 file 情况下的行为相同,但会持续尝试从文件中读取(和处理)更多数据,直到被 stop_trace_client/1 停止。 WrapFilesSpec 不允许用作此 Type 的第二个参数。

如果 Typeip,则客户端连接到主机 Hostname 上的 TCP/IP 端口 PortNumber,并从那里读取跟踪消息,直到 TCP/IP 连接关闭。如果未指定 Hostname,则假定为本地主机。

例如,可以让跟踪消息通过网络发送到另一个 Erlang 节点(最好不是分布式节点),并在该节点上进行格式化。

在节点 stack 上,存在一个 Erlang 节点 ant@stack。在 shell 中,键入以下内容

ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
<0.17.0>
ant@stack> dbg:p(self(), send).
{ok,1}

现在,所有跟踪消息都将发送到跟踪端口驱动程序,该驱动程序又在 TCP/IP 端口 4711 上侦听连接。如果我们想在另一个节点(最好在另一个主机上)上查看消息,我们可以这样做

1> dbg:trace_client(ip, {"stack", 4711}).
<0.42.0>

如果我们现在从节点 ant@stack 上的 shell 发送消息,其中来自 shell 的所有发送都被跟踪

ant@stack> self() ! hello.
hello

以下内容将出现在启动跟踪客户端的节点的控制台上

(<0.23.0>) <0.23.0> ! hello
(<0.23.0>) <0.22.0> ! {shell_rep,<0.23.0>,{value,hello,[],[]}}

最后一行是由于 Erlang shell 中的内部消息传递而生成的。 pid 将会有所不同。

链接到此函数

trace_client(类型, 参数, 处理程序规范)

查看源代码
-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().

此函数的工作方式与 trace_client/2 完全相同,但允许您编写自己的处理程序函数。

处理程序函数的工作方式与 tracer/2 中描述的类似,但也必须准备好处理 {drop, N} 形式的跟踪消息,其中 N 是丢弃的消息数。仅当使用 ip 跟踪驱动程序时,才会出现此伪跟踪消息。

对于跟踪类型 file,伪跟踪消息 end_of_trace 将出现在跟踪结束时。在这种情况下,处理程序函数的返回值将被忽略。

链接到此函数

trace_port(类型, 参数)

查看源代码
-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().

创建一个生成跟踪端口的 fun,它适合作为 tracer/2 的第二个参数。

示例

dbg:tracer(port, dbg:trace_port(ip, 4711)).

跟踪端口是 Erlang 端口,用于直接处理跟踪消息的动态链接驱动程序,而无需将它们作为消息发送到 Erlang 进程的开销。使用跟踪端口可以显著降低跟踪带来的开销。

目前实现了两个跟踪驱动程序:fileip 跟踪驱动程序。

file 驱动程序将所有跟踪消息发送到一个或多个二进制文件中,然后可以使用 trace_client/2 函数从这些文件中提取和处理它们。

ip 驱动程序打开一个 TCP/IP 端口侦听端口。当客户端(最好通过在另一个 Erlang 节点上调用 trace_client/2 启动)连接时,所有跟踪消息都将通过 IP 网络发送,以供远程客户端进一步处理。

file 跟踪驱动程序需要一个文件名或一个包装文件规范作为参数。写入文件时具有高度缓冲,因此无法保证在系统崩溃时所有内容都保存在文件中。

包装文件规范用于限制跟踪消耗的磁盘空间。跟踪写入到数量有限的文件中,每个文件的大小有限。实际文件名是 Filename ++ SeqCnt ++ Suffix,其中 SeqCnt0 计数到 WrapCnt,然后再次从 0 循环计数。当写入当前文件的跟踪项使其长度超过 WrapSize 时,该文件将关闭,如果此包装跟踪中的文件数量与 WrapCnt 一样多,则将删除最旧的文件,并打开一个新文件作为当前文件。因此,当停止包装跟踪时,最多会保存 WrapCnt 个跟踪文件,每个文件的大小至少为 WrapSize(但不会大太多),最后一个文件除外,该文件甚至可能为空。默认值为 WrapSize = 128*1024WrapCnt = 8

文件名中的 SeqCnt 值都在 0WrapCnt 的范围内,循环序列中存在间隙。需要此间隙来查找跟踪的末尾。

如果 WrapSize 指定为 {time, WrapTime},则当当前文件打开超过 WrapTime 毫秒时,无论其是否为空,都会关闭该文件。

ip 跟踪驱动程序有一个 QueSize 消息的队列等待传递。如果驱动程序无法以运行时系统生成消息的速度传递消息,则会发送一条特殊消息,指示有多少消息被丢弃。该消息将作为元组 {drop, N} 到达 trace_client/3 中指定的处理程序函数,其中 N 是丢弃的连续消息的数量。在大量跟踪的情况下,很可能发生丢弃,如果没有任何客户端读取跟踪消息,则肯定会发生丢弃。 QueSize 的默认值为 200。

链接到此函数

trace_port_control(操作)

查看源代码
-spec trace_port_control(Operation :: term()) -> term().

等同于 trace_port_control(node(), 操作)

链接到此函数

trace_port_control(节点名, 操作)

查看源代码
-spec trace_port_control(Nodename :: node(), Operation :: term()) ->
                            ok | {ok, Result :: term()} | {error, Reason :: term()}.

此函数用于对给定节点(节点名)上的活动跟踪端口驱动程序执行控制操作。

允许的操作及其返回值取决于使用的跟踪驱动程序。

如果操作成功,则返回 ok{ok, Result},如果当前跟踪器是进程,或者如果它是端口不支持该操作,则返回 {error, Reason}

Operation 允许的值为:

  • flush - 此函数用于刷新跟踪端口驱动程序持有的内部缓冲区。目前只有 file 跟踪驱动程序支持此操作。返回 ok

  • get_listen_port - 返回 {ok, IpPort},其中 IpPort 是驱动程序监听套接字使用的 IP 端口号。只有 ip 跟踪驱动程序支持此操作。

-spec tracer() -> {ok, pid()} | {error, already_started}.

在本地节点上启动一个服务器,该服务器将接收所有跟踪消息。

所有后续对 p/2 的调用都会导致消息发送到新启动的跟踪服务器。

以这种方式启动的跟踪服务器将简单地在 Erlang Shell 中显示格式化的跟踪消息(即,使用 io:format/2)。有关如何自定义跟踪消息处理程序,请参阅 tracer/2

要在远程节点上启动类似的跟踪器,请使用 n/1

链接到此函数

tracer(类型, 数据)

查看源代码
-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().

在本地节点上启动具有附加参数的跟踪器服务器。

Type 指示应如何处理跟踪消息

  • process - 由接收进程处理
  • port - 由端口处理;请参阅 trace_port/2
  • module - 由跟踪器模块处理;请参阅 erl_tracer
  • file - 通过将它们打印到文件来处理

如果 Typeprocess,则 Data 应该是一个消息处理函数 (HandlerSpec)。对于每个跟踪消息,将调用处理函数(它应该是一个带有两个参数的 fun),第一个参数包含消息本身,第二个参数包含上次调用 fun 的返回值。HandlerSpecInitialData 部分中指定了第二个参数的初始值。HandlerFun 可以选择在被调用时采取任何适当的操作,并且可以通过返回状态来保存下一次调用的状态。

如果 Typeport,那么第二个参数应该是一个不带参数的 fun,当调用时,它会返回一个新打开的跟踪端口。这样的 fun 最好通过调用 trace_port/2 生成。

如果 Typemodule,则 Data 应该是一个描述用于跟踪的 erl_tracer 模块和用于该跟踪器模块的状态的元组,或者一个返回这种元组的 fun。

如果 Typefile,则 Data 应该是一个文件名,指定所有跟踪将打印到的文件。

如果返回错误,可能是因为跟踪服务器已经在运行 ({error,already_started}),或者是因为 HandlerFun 引发了异常。

要在远程节点上启动类似的跟踪器,请使用 tracer/3

链接到此函数

tracer(节点名, 类型, 数据)

查看源代码
-spec tracer(Nodename :: node(), Type :: term(), Data :: term()) ->
                {ok, Nodename :: node()} | {error, Reason :: term()}.

此函数等同于 tracer/2,但在给定节点上运行。

在节点 (Nodename) 上启动跟踪器,并将该节点添加到被跟踪节点列表中。

注意

此函数不等同于 n/1。 虽然 n/1 启动一个进程跟踪器,它将所有跟踪信息重定向到本地节点(即跟踪控制节点)上的进程跟踪器,但 tracer/3 启动任何类型的跟踪器,独立于跟踪控制节点上的跟踪器类型。

有关详细信息,请参阅 tracer/2

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

将会话期间保存的所有匹配规范(通过调用 tp/2tpl/2)以及内置匹配规范,保存在名称由 名称 指定的文本文件中。

wtp 代表 write trace patterns(写入跟踪模式)。

文件的格式是文本格式,这意味着可以使用文本编辑器进行编辑,然后使用 rtp/1 恢复。

文件中的每个匹配规范都以句点 (.) 结尾,并且可以将新的(语法正确的)匹配规范手动添加到文件中。

该函数返回 ok,或者一个错误元组,其中第二个元素指示写入文件失败的原因。