LoginSignup
1
1

More than 5 years have passed since last update.

# Erlangのトレースツールttbを使ってみる

Posted at

実行時のトレース結果を見ていると特定の関数が目立って呼ばれているとか、処理の流れを俯瞰できたりと役に立ちましたので紹介します。
Erlang 19.1で動作確認しています。

準備

トレースするプログラムを用意します。

calc.erl
-module(calc).

-export([inc/1]).
-export([add/2]).

inc(A) -> add(A, 1).
add(A, B) -> A + B.

トレース処理はやや煩雑ですので便利関数を用意します。
また出力を見やすく整形します。

util.erl
-module(util).

-export([start/1]).
-export([stop/0]).

%% see http://erlang.org/doc/apps/observer/ttb_ug.html
%% see http://erlang.org/doc/man/dbg.html

start(Mods) ->
    ttb:tracer(),
    ttb:p(all, call),
    lists:foreach(fun(Mod) -> ttb:tp(Mod, caller) end, Mods).

stop() ->
    {stopped, Dir} = ttb:stop(return_fetch_dir),
    ttb:format(Dir, {handler, {fun show/4, []}}).

%% private
show(_Fd, Trace, _TraceInfo, State) ->
    case Trace of
    {_, _, _, {M1, F1, A1}, {M2, F2, A2Length}, TimeStamp} ->
        {_, _, MicroSec} = TimeStamp,
        {{Y, M, D}, {HH, MM, SS}} = calendar:now_to_universal_time(TimeStamp),
        io:format("time:~p/~p/~p ~p:~p:~p:~p\tfrom:~p:~p/~p\tto:~p:~p/~p~n", [Y, M, D, HH, MM, SS, MicroSec / 1000.0, M2, F2, A2Length, M1, F1, length(A1)]);
    _ ->
        io:format("unknown ~p~n", [Trace])
    end,
    State.

動作デモ

% erl
Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]

Eshell V8.1  (abort with ^G)

# コンパイル
1> c(calc).
{ok,calc}
2> c(util).
{ok,util}

# トレース開始
3> util:start([calc]).
ok

# トレース対象の処理を実行
4> calc:inc(1).
2
5> calc:add(1, 2).
3

# トレース終了、結果表示
6> util:stop().
Stored logs in /home/tadokoro/git/erlang_ttb/ttb_upload_ttb-20161109-185813
time:2016/11/9 9:58:13:949.357  from:erl_eval:do_apply/6        to:calc:inc/1
time:2016/11/9 9:58:13:949.717  from:erl_eval:do_apply/6        to:calc:add/2
unknown end_of_trace
ok

トレースの流れ

  1. 最初に ttb:tracer() します
  2. ttb:p(all, call) 等としてトレース対象を決めます。callの他にはsend, receive, messageなど色々。詳細はdbgのp(Items, Flags)
  3. ttb:tp(Mod, caller) 等としてトレースを有効化するモジュール、トレース位置(呼び出し時か、戻り時か)を決めます。詳細はttb
  4. トレースしたい処理を実行します
  5. {stopped, Dir} = ttb:stop(return_fetch_dir) 等としてトレースを止めて、ログ保存先を取得
  6. ttb:format(Dir) とするとトレース結果が表示されます。出力フォーマットを変えたい場合は ttb:format(Dir, {handler, {fun show/4, []}}) 等としてフォーマット関数(この例ではshow)を指定します。詳細はttb

備考

トレース実行後は以下のようなファイルが自動で作成されます

ttb_last_config
ttb_upload_ttb-20161109-184359/
├── nonode@nohost-ttb
└── nonode@nohost-ttb.ti

ttbが使えるはずなのに、rebar3でビルド後に「exception error: undefined function ttb:tracer/0」などと表示される場合は、rebar.configのrelxのdepへobserverを追加すると良です

エラーが消えてttbが使えるようになります

まとめ

rubyのtracerに似たものがErlangにもないかと調べたところ、ttbが見つかったので使ってみました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1