在Erlang中使用trace和dbg


70

我正在尝试开始使用erlang:trace/3dbg模块来跟踪实时生产系统的行为,而无需关闭服务器。

文档不透明的(轻描淡写),并且在线上似乎没有任何有用的教程。

我用了一整天做的就是捕捉什么是在一个特定的功能,试图一丝适用于发生Module:Function使用dbg:cdbg:p,但与所有没有成功。

有人对在实时Erlang系统中如何使用跟踪有一个简洁的解释吗?


Answers:


8

如果您希望图形示踪然后尝试erlyberly。它使您可以选择要跟踪的功能(当前在所有进程上)并处理dbg API。

但是,它不能防止过载,因此不适用于生产系统。

在此处输入图片说明


97

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

> 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。要删除功能,请调用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()的进程。这些项目在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:tracedbg几乎可以满足您的所有需求。

活动节点的黄金法则是仅生成一定数量的跟踪输出到外壳程序,让您键入dbg:stop_clear().。:)

我经常使用跟踪器,该跟踪器在发生许多事件后会自动停止。例如:

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

如果您正在寻找在远程节点(或多个节点)调试,搜索paneperinvisoonviso


2
到目前为止,我还无法跟踪将任何内容发送到外壳:(
Gordon Guthrie

您说这些是非活动节点上的基本步骤...大概是因为在活动节点上,您只会进入shell滚动(并丢失)吗?
Gordon Guthrie

1
跟踪需要系统中的一些资源。如果跟踪频繁发生的事件,则可能会降低性能。在最坏的情况下,您将失去联系,并且它会变成-繁荣-。
Zed

1
在实时系统上,我将非常详细地介绍函数调用,包括一些参数匹配。同样,在大多数情况下,您可以将跟踪限制为一个进程而不是全部。
Zed

2
实际上,您可以仅使用dbg进行集群/远程节点调试。dbg:n(Node)设置Node为与您所在的节点相同的跟踪。
archaelus

24

在实时系统上,我们很少跟踪到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( ... ).

  • 正如Zed的回答所示。

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

  • 正如Zed的回答所示。

<42> dbg:stop_clear().

  • 再次是要确保所有迹线都已写入输出,并避免了以后的不便之处。

您可以:

  • 通过在外壳中定义一些fun()-来添加触发器,以在给定的时间或事件停止跟踪。递归fun()-s是实现此目的的最佳方法,但是在应用它们时要非常小心。

  • 应用各种各样的模式匹配以确保仅使用具有特定类型参数的特定函数调用来跟踪特定过程...

不久前,我遇到一个问题,当我们必须检查ETS表的内容时,并且在出现某些条目时,我们不得不在2-3分钟内停止跟踪。

我还建议Francesco Cesarini写的《 Erlang Programming》一书。(Erlang编程@ Amazon


9

“ dbg”模块是非常底层的东西。我经常使用两种技巧来完成通常需要执行的任务。

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.