我正在尝试使用erlang:trace / 3和dbg模块来跟踪实时生产系统的行为,而无需关闭服务器。
documentation为opaque(说得温和),似乎没有任何有用的在线教程。
我花了一整天时间尝试做的是通过尝试将跟踪应用到模块来捕获特定函数中发生的事情:使用dbg:c和dbg:p的函数但是根本没有成功...
有没有人对如何在实时Erlang系统中使用跟踪进行简洁的解释?
答案 0 :(得分:91)
跟踪函数调用的基本步骤是在非活动节点上:
> 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.
您可以同时跟踪多个功能。通过为每个函数调用tp
来添加函数。如果要跟踪未导出的函数,则需要调用tpl
。要删除功能,请以类似方式致电ctp
或ctpl
。一些通用的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()来选择要跟踪的进程。这些项目在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
}).
如果您要在远程节点(或多个节点)上寻找调试,请搜索pan
,eper
,inviso
或onviso
。
答案 1 :(得分:22)
在实时系统上,我们很少追溯到shell。 如果系统配置良好,那么它已经收集了打印到shell的Erlang日志。我不必强调为什么这在任何活节点中都是至关重要的......
让我详细说明跟踪文件:
可以跟踪到文件,这将生成可以在以后转换和解析的二进制输出。 (用于进一步分析或自动控制系统等)
一个例子可能是:
跟踪包装的多个文件(12x50 MB)。在使用如此大的跟踪之前,请务必检查可用的磁盘空间!
dbg:tracer(port,dbg:trace_port(file,{"/log/trace",wrap,atom_to_list(node()),50000000,12})).
dbg:p(all,[call,timestamp,return_to]).
那说让我们来看一下基本的跟踪命令序列:
< 1> dbg:stop_clear().
< 2> dbg:tracer().
< 3> dbg:p(all,[call, timestamp]).
< 4> dbg:tp( ... ).
< 5> dbg:tpl( ... ).
< 42> dbg:stop_clear().
您可以:
通过在shell中定义一些fun() - s来添加触发器,以在给定时间或事件处停止跟踪。递归fun() - s是最好的实现这一点,但在应用它们时要非常小心。
应用各种模式匹配,以确保您只使用特定类型的参数跟踪具体函数调用的特定进程...
我有一个问题,当我们不得不检查ETS表的内容和某个条目的外观时,我们必须在2-3分钟内停止跟踪。
我还建议由Francesco Cesarini编写的Erlang Programming一书。 (Erlang Programming @ Amazon)
答案 2 :(得分:9)
'dbg'模块是非常低级的东西。我非常使用两种黑客 经常用于我通常需要的任务。
在http://www.snookles.com/erlang/user_default.erl使用Erlang CLI / shell扩展代码。它最初是由Serge Aleynikov编写的(据我所知) 是一个有用的“这就是我如何添加自定义函数到shell”的例子。编 模块并编辑〜/ .erlang文件以指向其路径(请参阅顶部的注释 该文件)。
使用redbug实用程序集合中捆绑的“EPER”实用程序。 使用'dbg'可以在几秒钟内创建数百万个跟踪事件。干 所以在生产环境中可能是灾难性的。用于开发或生产用途, redbug几乎不可能杀死具有迹线引起的过载的运行系统。
答案 3 :(得分:7)