web-dev-qa-db-ja.com

Erlangでのトレースとdbgの使用

サーバーを停止することなく、稼働中の本番システムの動作を追跡するために、erlang:trace/3とdbgモジュールの使用を開始しようとしています。

documentationopaque (控えめに言っても)であり、オンラインで役に立つチュートリアルはないようです。

私が一日中費やしたことは、dbg:cとdbg:pを使用してmodule:functionにトレースを適用しようとして、特定の関数で何が起こっているのかをキャプチャすることでしたが、成功しませんでした...

ライブErlangシステムでトレースを使用する方法について簡潔な説明がありますか?

65
Gordon Guthrie

グラフィカルなトレーサーを使用する場合は、 erlyberly を試してください。 (現時点ですべてのプロセスで)トレースする関数を選択し、dbg APIを処理できます。

ただし、過負荷に対しては保護されないため、実稼働システムには適していません。

enter image description here

7
Andy Till

関数呼び出しのトレースの基本的な手順は、非ライブノード上にあります。

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

dbgはほとんどすべてを行うため、_erlang:trace_を直接呼び出す必要はないでしょう。

ライブノードの黄金律は、シェルへのトレース出力の量のみを生成することです。これにより、dbg:stop_clear().と入力できます。 :)

多くの場合、多くのイベントの後に自動的に停止するトレーサーを使用します。例えば:

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

リモートノード(または複数のノード)でデバッグする場合は、paneperinviso、またはonvisoを検索します。

92
Zed

ライブシステムでは、シェルにトレースすることはほとんどありません。システムが適切に構成されていれば、シェルに出力されたErlangログをすでに収集しています。ライブノードでこれが重要である理由を強調する必要はありません...

ファイルへのトレースについて詳しく説明しましょう:

ファイルにトレースすることができます。これにより、後で変換および解析できるバイナリ出力が生成されます。 (さらなる分析または自動制御システムなどのため)

例は次のとおりです。

  • ラップされた複数のファイル(12x50メガバイト)にトレースします。このような大きなトレースを使用する前に、常に使用可能なディスク領域を確認してください!

    _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()-sを定義してトリガーを追加し、特定の時間またはイベントでトレースを停止します。再帰的なfun()-sはこれを達成するのに最適ですが、それらを適用するときは非常に注意してください。

  • 多種多様なパターンマッチングを適用して、特定のタイプの引数を持つ特定の関数呼び出しで特定のプロセスのみをトレースするようにします...

しばらく前に問題がありました。ETSテーブルの内容を確認する必要があり、特定のエントリが表示されたら、2〜3分以内にトレースを停止する必要がありました。

また、フランチェスコ・セサリーニによって書かれた本Erlang Programmingもお勧めします。 ( Erlang Programming @ Amazon

22
cdlf

「dbg」モジュールは非常に低レベルのものです。私がよく必要とするタスクのために非常に頻繁に使用する2つのハックがあります。

  1. http://www.snookles.com/erlang/user_default.erl でErlang CLI/Shell拡張コードを使用します。もともとは(私が知る限り)Serge Aleynikovによって書かれたもので、「シェルにカスタム関数を追加する方法」の例として有用です。モジュールをコンパイルし、そのパスを指すように〜/ .erlangファイルを編集します(ファイルの上部にあるコメントを参照)。

  2. [〜#〜] eper [〜#〜] ユーティリティのコレクションにバンドルされている " redbug "ユーティリティを使用します。 「dbg」を使用すると、数秒で数百万のトレースイベントを簡単に作成できます。実稼働環境でこれを行うと、悲惨な結果を招く可能性があります。開発または実稼働で使用する場合、redbugはトレースによって引き起こされる過負荷で実行中のシステムを強制終了することをほぼ不可能にします。