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

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

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

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

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

【问题讨论】:

标签: debugging erlang trace


【解决方案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”模块是相当低级的东西。我非常使用两种技巧 经常用于我通常需要的任务。

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 2017-04-16
        • 2015-11-07
        • 1970-01-01
        • 2012-09-08
        • 2016-11-30
        • 1970-01-01
        • 2017-02-12
        相关资源
        最近更新 更多