Skip to content

Instantly share code, notes, and snippets.

@hufeng
Forked from andrzejsliwa/output
Created October 21, 2018 13:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hufeng/6de4a47fd7051e2aa3659b6b11debda9 to your computer and use it in GitHub Desktop.
Save hufeng/6de4a47fd7051e2aa3659b6b11debda9 to your computer and use it in GitHub Desktop.
Erlang tracing (nested and flat)
~/erlang_learning $ erl
Erlang R15B03 (erts-5.9.3.1) [source] [64-bit] [smp:8:8] [async-threads:0] [hipe] [kernel-poll:false] [dtrace]
Eshell V5.9.3.1 (abort with ^G)
(erlang_learning@127.0.0.1)1> trace(recursive).
ok
(erlang_learning@127.0.0.1)2> recursive:fac(10).
call: <0.42.0> recursive:fac(10), level: 0
call: <0.42.0> recursive:fac(9), level: 1
call: <0.42.0> recursive:fac(8), level: 2
call: <0.42.0> recursive:fac(7), level: 3
call: <0.42.0> recursive:fac(6), level: 4
call: <0.42.0> recursive:fac(5), level: 5
call: <0.42.0> recursive:fac(4), level: 6
call: <0.42.0> recursive:fac(3), level: 7
call: <0.42.0> recursive:fac(2), level: 8
call: <0.42.0> recursive:fac(1), level: 9
call: <0.42.0> recursive:fac(0), level: 10
retn: <0.42.0> recursive:fac -> 1, level: 10
retn: <0.42.0> recursive:fac -> 1, level: 9
retn: <0.42.0> recursive:fac -> 2, level: 8
retn: <0.42.0> recursive:fac -> 6, level: 7
retn: <0.42.0> recursive:fac -> 24, level: 6
retn: <0.42.0> recursive:fac -> 120, level: 5
retn: <0.42.0> recursive:fac -> 720, level: 4
retn: <0.42.0> recursive:fac -> 5040, level: 3
retn: <0.42.0> recursive:fac -> 40320, level: 2
retn: <0.42.0> recursive:fac -> 362880, level: 1
retn: <0.42.0> recursive:fac -> 3628800, level: 0
3628800
(erlang_learning@127.0.0.1)3> trace_off().
ok
(erlang_learning@127.0.0.1)4> tracen(recursive).
<0.42.0> recursive:module_info()
<0.42.0> [{exports,[{fac,1},{module_info,0},{module_info,1}]},
{imports,[]},
{attributes,[{vsn,[183699004504069682905172544172501704709]}]},
{compile,[{options,[{outdir,"ebin"},debug_info,{i,"include"}]},
{version,"4.8.2"},
{time,{2013,9,12,7,4,16}},
{source,"/Users/andrzejsliwa/erlang_learning/apps/erlang_learning/src/recursive.erl"}]}]
ok
(erlang_learning@127.0.0.1)5> recursive:fac(10).
<0.42.0> recursive:fac(10)
<0.42.0> | recursive:fac(9)
<0.42.0> | | recursive:fac(8)
<0.42.0> | | | recursive:fac(7)
<0.42.0> | | | | recursive:fac(6)
<0.42.0> | | | | | recursive:fac(5)
<0.42.0> | | | | | | recursive:fac(4)
<0.42.0> | | | | | | | recursive:fac(3)
<0.42.0> | | | | | | | | recursive:fac(2)
<0.42.0> | | | | | | | | | recursive:fac(1)
<0.42.0> | | | | | | | | | | recursive:fac(0)
<0.42.0> | | | | | | | | | | 1
<0.42.0> | | | | | | | | | 1
<0.42.0> | | | | | | | | 2
<0.42.0> | | | | | | | 6
<0.42.0> | | | | | | 24
<0.42.0> | | | | | 120
<0.42.0> | | | | 720
<0.42.0> | | | 5040
<0.42.0> | | 40320
<0.42.0> | 362880
<0.42.0> 3628800
3628800
-module(user_default).
-export([help/0]).
-export([p/1, p/2]).
-export([pn/1, pn/2]).
-export([yy/1, yp/1]).
-export([reloader/0]).
-export([trace/1, trace/2]).
-export([tracen/1, tracen/2]).
-export([trace_off/0]).
-export([untrace/1, untrace/2]).
%% output helpers for shell
p(String) -> io:format(String).
p(String, Args) -> io:format(String, Args).
pn(String) -> p(String ++ "~n").
pn(String, Args) -> p(String ++ "~n", Args).
yy(Term) -> pn("~w", [Term]).
yp(Term) -> pn("~p", [Term]).
reloader() -> sync:go().
%% +-----------------------------------------------------------------+
%% | NESTED TRACER |
%% +-----------------------------------------------------------------+
nested_tracer() ->
dbg:tracer(process, {fun nested_trace/2, 0}).
nested_trace({trace, Pid, call, {Mod, Fun, Args}}, Level) ->
pn("~p ~s~p:~p~s", [Pid, fill_spaces(Level), Mod, Fun, format_args(Args)]),
Level + 1;
nested_trace({trace, Pid, return_from, {_, _, _}, ReturnValue}, Level) ->
NewLevel = Level - 1,
pn("~p ~s~p", [Pid, fill_spaces(NewLevel), ReturnValue]),
NewLevel;
nested_trace(Any, Level) ->
pn("trace_msg: ~p", [Any]),
Level.
tracer() ->
dbg:tracer(process, {fun flat_trace/2, 0}).
flat_trace({trace, Pid, call, {Mod, Fun, Args}}, Level) ->
pn("call: ~p ~p:~p~s, level: ~w", [Pid, Mod, Fun, format_args(Args), Level]),
Level + 1;
flat_trace({trace, Pid, return_from, {Mod, Fun, _}, ReturnValue}, Level) ->
NewLevel = Level - 1,
pn("retn: ~p ~p:~p -> ~p, level: ~w", [Pid, Mod, Fun, ReturnValue, NewLevel]),
NewLevel;
flat_trace(Any, Level) ->
pn("trace_msg: ~p", [Any]),
Level.
fill_spaces(Level) ->
lists:duplicate(Level, "| ").
format_args(Args) ->
Args1 = io_lib:format("~w", [Args]),
Opts = [global, {return, list}],
Args2 = re:replace(Args1, "^\\[", "(", Opts),
Args3 = re:replace(Args2, "\\]$", ")", Opts),
re:replace(Args3, "\\,", ", ", Opts).
%% +-----------------------------------------------------------------+
%% | TRACING HELPERS |
%% +-----------------------------------------------------------------+
trace(Module) ->
tracer(), setup_tracing(Module).
trace(Module, Function) ->
tracer(), setup_tracing(Module, Function).
tracen(Module) ->
nested_tracer(), setup_tracing(Module).
tracen(Module, Function) ->
nested_tracer(), setup_tracing(Module, Function).
trace_off() -> dbg:stop().
untrace(Module) ->
{ok, _} = dbg:ctpl(Module), ok.
untrace(Module, Function) ->
{ok, _} = dbg:ctpl(Module, Function), ok.
setup_tracing(Module)
when is_atom(Module) ->
{ok, _} = dbg:p(all, call),
{ok, _} = dbg:tpl(Module, tracing_options()),
ok.
setup_tracing(Module, Function)
when is_atom(Module),
is_atom(Function) ->
{ok, _} = dbg:p(all, call),
{ok, _} = dbg:tpl(Module, Function, tracing_options()),
ok.
tracing_options() ->
[{'_', [], [{return_trace}, {exception_trace}]}].
%% +-----------------------------------------------------------------+
%% | HELP MENU |
%% +-----------------------------------------------------------------+
help() ->
shell_default:help(),
pn("~n** commands in module ~s (user helpers) **~n", [?MODULE]),
pn("reloader() -- run code reloader"),
pn("trace(Module) -- run tracing for 'Module'"),
pn("trace(Module, Function) -- run tracing for 'Function' of 'Module'"),
pn("tracen(Module) -- run tracing for 'Module' - nested way"),
pn("tracen(Module, Function) -- run tracing for 'Function' of 'Module' - nasted way"),
pn("trace_off() -- disable tracing"),
pn("untrace(Module) -- stop tracing 'Module'"),
pn("untrace(Module, Function) -- stop tracing 'Function' of 'Module'"),
pn("p(String) -- print string"),
pn("p(String, Args) -- print string with format"),
pn("pn(String) -- print string with ~~n"),
pn("pn(String, Args) -- print string with ~~n and format"),
pn("yy(Term) -- print raw term"),
pn("yp(Term) -- print term").
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment