如何在 Erlang 中使用 trace 和 dbg 来调试和跟踪我的程序?

Posted

技术标签:

【中文标题】如何在 Erlang 中使用 trace 和 dbg 来调试和跟踪我的程序?【英文标题】:How to use trace and dbg in Erlang to debug and trace my program? 【发布时间】:2010-12-29 14:52:47 【问题描述】:

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

documentation 是opaque(委婉地说),网上似乎没有任何有用的教程。

我花了一整天的时间试图通过尝试使用dbg:cdbg:pModule:Function 应用跟踪来捕获特定函数中发生的事情,但根本没有成功。

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

【问题讨论】:

github.com/massemanet/redbug 【参考方案1】:

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

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

如果您要在远程节点(或多个节点)上进行调试,请搜索 paneperinvisoonviso

【讨论】:

到目前为止,我还无法跟踪将 anything 发送到 shell :( 你说这些是非活动节点上的基本步骤......大概是因为在活动节点上你只会进入 shell 滚动(并丢失)? 跟踪需要系统提供一些资源。如果您跟踪频繁发生的事件,您可能会冒着表现的风险。在最坏的情况下,你会失去联系,然后-Boom-。 在实时系统上,我会对函数调用非常具体,包括一些参数匹配。此外,大多数情况下,您可以将跟踪限制为一个进程而不是全部。 您实际上可以只使用 dbg 进行集群/远程节点调试。 dbg:n(Node) 设置 Node 与您所在的节点进行相同的跟踪。【参考方案2】:

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

在将任何内容输入活动节点的 shell 之前,始终在测试节点上进行测试! 最好先有一个测试节点或副本节点来尝试脚本。

话虽如此,让我们看一下基本的跟踪命令序列:

dbg:stop_clear().

始终从刷新跟踪端口开始,并确保以前的跟踪不会干扰当前跟踪。

dbg:tracer().

启动跟踪器进程。

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

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

dbg:tp( ... ).

从 Zed 的回答中可以看出。

dbg:tpl( ... ).

从 Zed 的回答中可以看出。

dbg:stop_clear().

再次确保所有跟踪都写入输出并避免以后的任何不便。

您可以:

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

应用多种模式匹配,以确保您仅使用特定类型的参数调用特定函数调用来跟踪特定进程...

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

我还推荐 Francesco Cesarini 写的 Erlang Programming 一书。 (Erlang Programming @ Amazon)

【讨论】:

【参考方案3】:

“dbg”模块是相当低级的东西。我非常使用两种技巧 经常用于我通常需要的任务。

    在http://www.snookles.com/erlang/user_default.erl 使用 Erlang CLI/shell 扩展代码。它最初是由 Serge Aleynikov 写的(据我所知) 一直是一个有用的“这就是我向 shell 添加自定义函数的方式”示例。编译 模块并编辑您的 ~/.erlang 文件以指向其路径(请参阅顶部的注释 文件)。

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

【讨论】:

【参考方案4】:

如果您更喜欢图形跟踪器,请尝试erlyberly。它允许您选择要跟踪的函数(目前在所有进程上)并处理 dbg API。

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

【讨论】:

以上是关于如何在 Erlang 中使用 trace 和 dbg 来调试和跟踪我的程序?的主要内容,如果未能解决你的问题,请参考以下文章

Erlang Tracing:因果一致性?

使用erlang跟踪事件消息:trace_delivered / 1

Erlang 中的 Oracle DB 连接处理程序

连接 Erlang 和 mysql odbc 时出错

Erlang注册过程

尝试在 Erlang 中组合列表的问题