|
|
@ -8,7 +8,6 @@ |
|
|
|
, stl/0 %% tpTracerLog |
|
|
|
, stf/0 %% tpTracerFile |
|
|
|
|
|
|
|
|
|
|
|
%% pt函数 |
|
|
|
, pts/0 %% tpTracerShell |
|
|
|
, ptl/0 %% tpTracerLog |
|
|
@ -50,11 +49,17 @@ sts1() -> |
|
|
|
trace([test, {scope, [self()]}]). |
|
|
|
|
|
|
|
stl() -> |
|
|
|
trace([{app, eSync}, {scope, [new_processes]}], tpTracerLog). |
|
|
|
trace([test, {scope, [self()]}], tpTracerLog). |
|
|
|
|
|
|
|
stf() -> |
|
|
|
trace([{app, eSync}, {scope, [whereis(esSyncSrv)]}], tpTracerFile). |
|
|
|
|
|
|
|
stop() -> |
|
|
|
stop(?eTpfTracerId). |
|
|
|
|
|
|
|
stop(TracerId) -> |
|
|
|
supervisor:terminate_child(eTpf_sup, TracerId). |
|
|
|
|
|
|
|
pts() -> |
|
|
|
ok. |
|
|
|
|
|
|
@ -118,13 +123,7 @@ trace(Input, TracerMod, TracerOpts, TraceOpts) when is_list(Input) -> |
|
|
|
InputList = case is_list(Input) of true -> Input; _ -> [Input] end, |
|
|
|
doTrace(InputList, TracerMod, TracerOpts, TraceOpts). |
|
|
|
|
|
|
|
stop() -> |
|
|
|
stop(?eTpfTracerId). |
|
|
|
|
|
|
|
stop(TracerId) -> |
|
|
|
supervisor:terminate_child(eTpf_sup, TracerId). |
|
|
|
|
|
|
|
doTrace(InputList, TracerMod, TracerOpts, TraceOpts) -> |
|
|
|
doTrace(PidPortSpec, FlagList, TraceMods, TracerMod, TracerOpts, TraceOpts) -> |
|
|
|
_ = application:ensure_all_started(eTpf), |
|
|
|
|
|
|
|
TracerId = maps:get(tracerId, TraceOpts, ?eTpfTracerId), |
|
|
@ -137,76 +136,42 @@ doTrace(InputList, TracerMod, TracerOpts, TraceOpts) -> |
|
|
|
}) of |
|
|
|
{ok, TracerPid} -> |
|
|
|
_Mode = maps:get(mode, TraceOpts, trace), |
|
|
|
Tem0InputList = flattenInput(InputList, []), |
|
|
|
Tem1InputList = ensurePattern(Tem0InputList), |
|
|
|
LastInputList = ensureScope(Tem1InputList), |
|
|
|
traceInput(LastInputList, TracerPid, TraceOpts), |
|
|
|
LastTraceMods = flattenMods(TraceMods, []), |
|
|
|
traceInput(PidPortSpec, FlagList, LastTraceMods, TracerPid, TraceOpts), |
|
|
|
ok; |
|
|
|
_Err -> |
|
|
|
io:format("trace start error ~p~n", [_Err]) |
|
|
|
end. |
|
|
|
|
|
|
|
flattenInput([], Acc) -> |
|
|
|
lists:flatten(Acc); |
|
|
|
flattenInput([{callback, Mod, Fun} | Tail], Acc) when is_atom(Mod), is_atom(Fun) -> |
|
|
|
Input = flattenInput(Mod:Fun(), []), |
|
|
|
flattenInput(Tail, [Input | Acc]); |
|
|
|
flattenInput([{app, App} | Tail], Acc) when is_atom(App) -> |
|
|
|
flattenMods([], Acc) -> |
|
|
|
case lists:flatten(Acc) of |
|
|
|
[] -> |
|
|
|
['_']; |
|
|
|
AllMods -> |
|
|
|
AllMods |
|
|
|
end; |
|
|
|
flattenMods([{callback, Mod, Fun} | Tail], Acc) when is_atom(Mod), is_atom(Fun) -> |
|
|
|
Input = flattenMods(Mod:Fun(), []), |
|
|
|
flattenMods(Tail, [Input | Acc]); |
|
|
|
flattenMods([{app, App} | Tail], Acc) when is_atom(App) -> |
|
|
|
_ = application:load(App), |
|
|
|
{ok, Mods} = application:get_key(App, modules), |
|
|
|
flattenInput(Tail, [Mods | Acc]); |
|
|
|
flattenInput([Input | Tail], Acc) -> |
|
|
|
flattenInput(Tail, [Input | Acc]). |
|
|
|
|
|
|
|
ensurePattern(Input) -> |
|
|
|
case [S || S = {scope, _} <- Input] of |
|
|
|
Input -> ['_' | Input]; |
|
|
|
_ -> Input |
|
|
|
end. |
|
|
|
flattenMods(Tail, [Mods | Acc]); |
|
|
|
flattenMods([Input | Tail], Acc) -> |
|
|
|
flattenMods(Tail, [Input | Acc]). |
|
|
|
|
|
|
|
ensureScope(Input) -> |
|
|
|
case [S || S = {scope, _} <- Input] of |
|
|
|
[] -> [{scope, [processes]} | Input]; |
|
|
|
_ -> Input |
|
|
|
end. |
|
|
|
|
|
|
|
traceInput([], _, _) -> |
|
|
|
ok; |
|
|
|
traceInput([{scope, Scope} | Tail], TracerState, TraceOpts) -> |
|
|
|
traceInput(PidPortSpec, FlagList, TraceMods, TracerState, TraceOpts) -> |
|
|
|
% 每个进程只能由一个tracer进行跟踪。因此,跟踪已跟踪进程会失败。 |
|
|
|
|
|
|
|
% PidPortSpec |
|
|
|
%% all All currently existing processes and ports and all that will be created in the future. |
|
|
|
%% processes All currently existing processes and all that will be created in the future. |
|
|
|
%% ports All currently existing ports and all that will be created in the future. |
|
|
|
%% existing All currently existing processes and ports. |
|
|
|
%% existing_processes All currently existing processes. |
|
|
|
%% existing_ports All currently existing ports. |
|
|
|
%% new All processes and ports that will be created in the future. |
|
|
|
%% new_processes All processes that will be created in the future. |
|
|
|
%% new_ports All ports that will be created in the future. |
|
|
|
|
|
|
|
% FlagList |
|
|
|
%% We currently enable the following trace flags: |
|
|
|
%% - call: function calls |
|
|
|
%% - procs: process exit events; plus others we ignore |
|
|
|
%% - running: process being scheduled in/out |
|
|
|
%% - timestamp: events include the current timestamp |
|
|
|
%% - arity: function calls only include the arity, not arguments |
|
|
|
%% - return_to: return from functions |
|
|
|
%% - set_on_spawn: propagate trace flags to any children processes |
|
|
|
%% |
|
|
|
%% @todo It might be useful to count the number of sends |
|
|
|
%% or receives a function does. |
|
|
|
%ExtraFlags = [running || maps:get(running, TraceOpts, false)] ++ [send || maps:get(send, TraceOpts, false)], |
|
|
|
[ |
|
|
|
begin |
|
|
|
%erlang:trace(PidPortSpec, true, [call, procs, arity, return_to, set_on_spawn, {tracer, tpTracerNif, TracerState} | ExtraFlags]) |
|
|
|
erlang:trace(PidPortSpec, true, [call, {tracer, tpTracerNif, TracerState}]) |
|
|
|
end || PidPortSpec <- Scope |
|
|
|
erlang:trace(OnePidPortSpec, true, [{tracer, tpTracerNif, TracerState} | FlagList]) |
|
|
|
end || OnePidPortSpec <- PidPortSpec |
|
|
|
], |
|
|
|
traceInput(Tail, TracerState, TraceOpts); |
|
|
|
traceInput([Mod | Tail], TracerState, TraceOpts) when is_atom(Mod) -> |
|
|
|
|
|
|
|
MatchSpec = |
|
|
|
case TraceOpts of |
|
|
|
#{process_dump := true} -> |
|
|
@ -214,8 +179,13 @@ traceInput([Mod | Tail], TracerState, TraceOpts) when is_atom(Mod) -> |
|
|
|
_ -> |
|
|
|
true |
|
|
|
end, |
|
|
|
%% The module must be loaded before we attempt to trace it. |
|
|
|
_ = code:ensure_loaded(Mod), |
|
|
|
io:format("IMY****************** ~p~n ", [Mod]), |
|
|
|
_ = erlang:trace_pattern({Mod, '_', '_'}, [{'_', [], [{message, {process_dump}}]}], [local]), |
|
|
|
traceInput(Tail, TracerState, TraceOpts). |
|
|
|
|
|
|
|
[ |
|
|
|
begin |
|
|
|
%% The module must be loaded before we attempt to trace it. |
|
|
|
_ = code:ensure_loaded(OneTraceMods), |
|
|
|
io:format("IMY****************** ~p~n ", [OneTraceMods]), |
|
|
|
_ = erlang:trace_pattern({OneTraceMods, '_', '_'}, [{'_', [], [{message, {process_dump}}]}], [local]) |
|
|
|
end || OneTraceMods <- TraceMods |
|
|
|
], |
|
|
|
ok. |