Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion case-studies/meViolation/trace/trace_result.log
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
{exec,10016000}.
{node,nonode@nohost}.
{pid,209}.
{return,{value,<0.216.0>}}.
{return,{value,216}}.
{tracing,timeout}.
37 changes: 32 additions & 5 deletions src/cauder_trace.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
push/3,
pop/3,
get/2,
peek/2,
reverse_actions/1,
peek/2
]).
-export([
reverse/1,
map_pids/1,
to_log/1
]).

Expand Down Expand Up @@ -86,12 +89,36 @@ peek(Pid, Trace) ->
error
end.

-spec reverse_actions(Trace) -> NewTrace when
%%%=============================================================================

-spec reverse(Trace) -> NewTrace when
Trace :: cauder_trace:trace(),
NewTrace :: cauder_trace:trace().

reverse_actions(Trace) ->
maps:map(fun(_, Actions) -> lists:reverse(Actions) end, Trace).
reverse(Trace) ->
maps:map(fun(_, Actions) -> lists:reverse(map_pids(Actions)) end, Trace).

-spec map_pids(term()) -> term().

map_pids(List) when is_list(List) ->
lists:map(fun map_pids/1, List);
map_pids(Tuple) when is_tuple(Tuple) ->
list_to_tuple(lists:map(fun map_pids/1, tuple_to_list(Tuple)));
map_pids(Map) when is_map(Map) ->
maps:fold(
fun(K, V, Acc) ->
K1 = map_pids(K),
V1 = map_pids(V),
false = maps:is_key(K1, Acc),
Acc#{K1 => V1}
end,
#{},
Map
);
map_pids(Pid) when is_pid(Pid) ->
cauder_process:from_pid(Pid);
map_pids(Term) ->
Term.

-spec to_log(Trace) -> Log when
Trace :: cauder_trace:trace(),
Expand Down
34 changes: 21 additions & 13 deletions src/cauder_tracer.erl
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,10 @@ init({MainPid, TracedPid}) ->
NewState :: state().

handle_call(get_traces, _From, #state{trace = Trace0} = State) ->
Trace1 = cauder_trace:reverse_actions(Trace0),
Trace1 = cauder_trace:reverse(Trace0),
{reply, {ok, Trace1}, State};
handle_call(get_return_value, _From, #state{return = ReturnValue} = State) ->
{reply, ReturnValue, State};
{reply, cauder_trace:map_pids(ReturnValue), State};
%% ========== 'call' trace messages ========== %%
%% Generate message stamp
handle_call({trace, Pid, call, {cauder_tracer_erlang, send_centralized, [_, _]}}, _From, State) ->
Expand Down Expand Up @@ -454,29 +454,37 @@ get_uid(Stamp, #state{ets = Table, stamps = Map} = State) ->

-spec write_trace(Dir, TraceInfo) -> ok when
Dir :: file:filename(),
TraceInfo :: cauder_tracer:trace_info().
TraceInfo :: cauder_types:trace_info().

write_trace(Dir, TraceResult) ->
write_trace(Dir, TraceInfo) ->
% This not compile time safe but there is no other way to keep it human-friendly and simple
[trace_info | Values] = tuple_to_list(TraceResult),
Fields = record_info(fields, trace_info),
{Traces, ResultInfo} = maps:take(trace, maps:from_list(lists:zip(Fields, Values))),
[trace_info | Values] = tuple_to_list(TraceInfo),
{Trace, ResultInfo} = maps:take(trace, maps:from_list(lists:zip(Fields, Values))),

ok = filelib:ensure_dir(Dir),
case filelib:is_dir(Dir) of
true -> ok;
false -> ok = file:make_dir(Dir)
end,

ResultFile = filename:join(Dir, "trace_result.log"),
ResultContent = lists:join($\n, lists:map(fun(T) -> io_lib:format("~p.", [T]) end, maps:to_list(ResultInfo))),
ok = file:write_file(ResultFile, ResultContent),
ResultFilename = filename:join(Dir, "trace_result.log"),
write_terms(ResultFilename, maps:to_list(ResultInfo)),

maps:foreach(
fun(Pid, Actions) ->
File = filename:join(Dir, io_lib:format("trace_~b.log", [Pid])),
Content = lists:join($\n, lists:map(fun(T) -> io_lib:format("~p.", [T]) end, Actions)),
ok = file:write_file(File, Content)
Filename = filename:join(Dir, io_lib:format("trace_~b.log", [Pid])),
write_terms(Filename, Actions)
end,
Traces
Trace
).

-spec write_terms(Filename, Terms) -> ok when
Filename :: file:name_all(),
Terms :: [term()].

write_terms(Filename, Terms) ->
Lines = lists:map(fun(Term) -> io_lib:format("~w.", [Term]) end, Terms),
Joined = lists:join($\n, Lines),
Text = unicode:characters_to_binary(Joined),
file:write_file(Filename, Text).