Current section
Files
Jump to
Current section
Files
src/tr_ct.erl
-module(tr_ct).
-export([ with_trace/3 ]).
-export([ trace_checkpoint/2
, set_activation_checkpoint/2 ]).
-define(SPEC, tr_ct_spec).
-define(TR_ACTIVATE_AT, tr_activate_at).
-define(TR_START, start).
with_trace(Fun, Config0, Spec) ->
ct:log("with_trace (Spec = ~p)...", [Spec]),
Config = [{?SPEC, Spec} | Config0],
trace_checkpoint(?TR_START, Config),
Res = try Fun(Config)
catch Error:R:Stack ->
case Error of
error ->
ct:pal("Error ~p~nStack = ~p", [R, Stack]),
ttb_stop(),
error(R);
exit ->
ct:pal("Exit ~p~nStack = ~p", [R, Stack]),
ttb_stop(),
exit(R);
throw ->
ct:pal("Caught throw:~p", [R]),
throw(R)
end
end,
ct:log("Res = ~p", [Res]),
case get_spec(collect, Config, on_error) of
on_error ->
ct:log("Discarding trace", []),
tr_ttb:stop_nofetch();
always ->
ttb_stop()
end,
Res.
set_activation_checkpoint(Checkpoint, Config) ->
[{tr_activate_at, Checkpoint} | Config].
trace_checkpoint(Checkpoint, Config) ->
case trace_is_active(Config) of
true ->
case proplists:get_value(?TR_ACTIVATE_AT, Config, ?TR_START) of
Checkpoint ->
Dest = get_destination(Config),
Spec0 = get_spec(Config),
Spec = Spec0#{info => #{checkpoint => Checkpoint}},
TTBRes = tr_ttb:on_nodes(get_nodes(Config), Dest, Spec),
ct:log("Trace set up at checkpoint ~p: ~p",
[Checkpoint, TTBRes]);
_ ->
ok
end;
false ->
ok
end.
trace_is_active(Config) ->
lists:keymember(?SPEC, 1, Config).
ttb_stop() ->
Dir = tr_ttb:stop(),
Out = filename:join(filename:dirname(Dir), filename:basename(Dir) ++ ".txt"),
case tr_ttb:format(Dir, Out, #{limit => 10000}) of
{error, Reason} ->
ct:pal("TTB formatting error: ~p", [Reason]);
_ ->
ok
end,
ct:pal("Formatted trace log in ~s~n", [Out]).
get_destination(Config) ->
case get_spec(destination, Config) of
undefined ->
LogBase = log_base_name(Config),
fstring("~s.tr_ct", [LogBase]);
D ->
D
end.
get_nodes(Config) ->
get_spec(nodes, Config, [node()]).
get_spec(Key, Config) ->
get_spec(Key, Config, undefined).
get_spec(Key, Config, Default) ->
tr_ttb:cfg(get_spec(Config), Key, Default).
get_spec(Config) ->
case proplists:get_value(?SPEC, Config) of
undefined ->
#{};
Map when is_map(Map) ->
Map
end.
log_base_name(Config) ->
{_, LF} = lists:keyfind(tc_logfile, 1, Config),
[Base, []] = re:split(LF, <<"\\.html">>, [{return, list}]),
Base.
fstring(Fmt, Args) ->
lists:flatten(io_lib:format(Fmt, Args)).