在Erlang中使用trace和dbg

我正在尝试使用erlang:trace / 3和dbg模块来跟踪实时生产系统的行为,而不必closures服务器。

这个文档是不透明的 (说得温和些),在网上看来没有任何有用的教程。

我花了一整天的时间试图做的是通过尝试使用dbg:c和dbg:p来应用跟踪到module:function的函数来捕获特定函数中发生的事情。

有没有人有一个简单的解释如何使用跟踪现场Erlang系统?

跟踪函数调用的基本步骤是在非活动节点上:

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

您可以同时追踪多个function。 通过为每个函数调用tp来添加函数。 如果你想跟踪非导出函数,你需要调用tpl 。 要删除函数,以类似的方式调用ctpctpl 。 一些普通的tp电话是:

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

最后一个参数是匹配规范。 你可以使用dbg:fun2ms来玩。

您可以通过调用p()来select追踪的进程。 这些项目在erlang:trace下描述。 有些电话是:

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

我想你永远不需要直接调用erlang:trace ,因为dbg几乎可以为你做所有事情。

活动节点的黄金法则是只生成一定数量的跟踪输出到shell,这使您可以键入dbg:stop_clear(). 。 🙂

我经常使用一个跟踪器,在一些事件之后会自动停止。 例如:

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

如果您正在寻找远程节点(或多个节点)上的debugging,则searchpaninvisoinvisoonviso

在实时系统上,我们很less跟踪到shell。 如果系统configuration良好,那么它已经在收集打印到shell的Erlang日志。 我不需要强调,为什么这在任何活节点都是至关重要的…

让我详细说明跟踪文件:

可以跟踪到文件,这将产生一个二进制输出,可以稍后转换和parsing。 (用于进一步分析或自动控制系统等)

一个例子可能是:

  • 跟踪多个文件(12×50 Mbytes)。 在使用这么大的跟踪之前,请务必检查可用的磁盘空间!

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

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

    • 在进入活动节点的shell之前,总是在testing节点上进行testing!
    • build议首先有一个testing节点或副本节点来尝试脚本。

那么让我们来看一下基本的追踪命令序列:

<1> dbg:stop_clear().

  • 总是从冲洗跟踪端口开始,并确保先前的跟踪不会干扰当前跟踪。

<2> dbg:tracer().

  • 开始示踪过程。

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

  • 在这种情况下,我们正在追踪所有进程和函数调用。

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

  • 正如在Zed的答案中所看到的那样。

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

  • 正如在Zed的答案中所见。

dbg:stop_clear().

  • 同样是要确保所有的痕迹都写在输出中,并避免以后的不便。

您可以:

  • 通过在shell中定义一些fun() – s来添加触发器,以在给定时间或事件停止跟踪。 recursion的乐趣() – 是最好的实现这一点,但在应用这些时要非常小心。

  • 应用各种各样的模式匹配,以确保您只跟踪特定的过程与特定的函数调用与特定types的参数…

之前我有一个问题,当我们必须检查ETS表格的内容和某个条目的出现时,我们不得不在2-3分钟内停止追踪。

我还build议由Francesco Cesarini编写的Erlang程序。 ( Erlang编程@ Amazon )

'dbg'模块是相当低级的东西。 我经常需要使用两种黑客来执行这些任务。

  1. 使用http://www.snookles.com/erlang/user_default.erl上的Erlang CLI / shell扩展代码。 它是由Serge Aleynikov最初编写的(据我所知),并且一直是一个有用的“所以这就是我如何添加自定义函数到shell”的例子。 编译模块并编辑〜/ .erlang文件以指向其path(请参阅文件顶部的注释)。

  2. 使用EPER收集的实用程序中捆绑的“ redbug ”实用程序。 使用'dbg'很容易在几秒钟内创build数百万个跟踪事件。 在生产环境中这样做可能是灾难性的。 对于开发或生产使用来说,使用redbug几乎不可能杀死一个正在运行的系统,导致过载。

如果你更喜欢一个graphics跟踪器,然后尝试erlyberly 。 它允许你select你想跟踪的function(在当前的所有进程中)并处理dbg API。

但是它不能防止过载,所以不适合生产系统。

在这里输入图像说明