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

我试图开始使用 erlang:trace/3dbg模块来跟踪一个实时生产系统的行为,而不用关闭服务器。

文件不透明(委婉地说) ,在网上似乎没有任何有用的教程。

我花了一整天的时间试图通过使用 dbg:cdbg:pModule:Function应用跟踪来捕捉特定函数中发生的情况,但是一无所获。

有没有人能简洁地解释一下如何在实时 Erlang 系统中使用跟踪?

28468 次浏览

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

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

最后一个参数是一个匹配规范。

您可以通过调用 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

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

让我详细说明文件跟踪:

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

例如:

  • 跟踪到多个包装的文件(12x50MB)。 < strong > 在使用如此大的跟踪之前,请总是检查可用的磁盘空间!

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

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

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

也就是说,让我们看看一个基本的跟踪命令序列:

< 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 来添加触发器,以便在给定的时间或事件中停止跟踪。递归乐趣()-s 是实现这一点的最佳方法,但是在应用这些方法时要非常小心。

  • 应用各种各样的模式匹配,以确保您只跟踪特定进程的特定函数调用和特定类型的参数... ..。

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

我也推荐弗朗西斯科 · 塞萨里尼写的《二郎程序设计》(Erlang Programming@Amazon)

Dbg 模块是非常低级的东西 经常去完成我需要完成的任务。

  1. http://www.snookles.com/erlang/user_default.erl使用 Erlang CLI/shell 扩展代码。它最初是由 Serge Aleynikov 写的(据我所知) 是一个有用的例子,“这就是我如何向 shell 中添加自定义函数” 然后编辑 ~/. erlang 文件以指向它的路径(参见顶部的注释)

  2. 使用 艾柏实用程序集合中捆绑的“ 红虫”实用程序。 使用“ dbg”很容易在几秒钟内创建数百万个跟踪事件 因此在生产环境中可能是灾难性的。对于开发或生产用途, Redbug 使得几乎不可能用跟踪引起的过载来终止正在运行的系统

如果您想要一个图形跟踪器,然后尝试 一点点。它允许您选择希望跟踪的函数(目前在所有进程上)并处理 dbg API。

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

enter image description here