|
|
@ -10,7 +10,6 @@ |
|
|
|
|
|
|
|
]). |
|
|
|
|
|
|
|
|
|
|
|
-type pattern() :: module() | {app, atom()} | {callback, module(), atom()}. |
|
|
|
-type scope() :: {scope, [pid() | port() | all | processes | ports |existing | existing_processes | existing_ports |new | new_processes | new_ports]}. |
|
|
|
-type input() :: [pattern() | scope()]. |
|
|
@ -42,14 +41,15 @@ trace(Input, TracerMod, TracerOpts, Opts) -> |
|
|
|
|
|
|
|
do_trace(Input0, TracerMod, TracerOpts, Opts) -> |
|
|
|
%% @todo Remove eventually? |
|
|
|
_ = application:ensure_all_started(looking_glass), |
|
|
|
_ = application:ensure_all_started(eTpf), |
|
|
|
|
|
|
|
%% Start the pool of tracer processes. |
|
|
|
PoolID = maps:get(pool_id, Opts, default), |
|
|
|
PoolSize = maps:get(pool_size, Opts, erlang:system_info(schedulers)), |
|
|
|
true = PoolSize > 0, |
|
|
|
{ok, PoolPid} = supervisor:start_child(looking_glass_sup, #{ |
|
|
|
{ok, PoolPid} = supervisor:start_child(eTpf_sup, #{ |
|
|
|
id => PoolID, |
|
|
|
start => {lg_tracer_pool, start_link, [PoolSize, TracerMod, TracerOpts]}, |
|
|
|
start => {tpTracerPool, start_link, [PoolSize, TracerMod, TracerOpts]}, |
|
|
|
restart => temporary, |
|
|
|
type => supervisor |
|
|
|
}), |
|
|
@ -100,20 +100,20 @@ trace_input([{scope, Scope} | Tail], TracerState, Opts) -> |
|
|
|
%% |
|
|
|
%% @todo It might be useful to count the number of sends |
|
|
|
%% or receives a function does. |
|
|
|
ExtraFlags = [running || maps:get(running, Opts, false)] |
|
|
|
++ [send || maps:get(send, Opts, false)], |
|
|
|
_ = [erlang:trace(PidPortSpec, true, [ |
|
|
|
call, procs, timestamp, arity, return_to, set_on_spawn, |
|
|
|
{tracer, lg_tracer, TracerState} |
|
|
|
| ExtraFlags |
|
|
|
]) |
|
|
|
|| PidPortSpec <- Scope], |
|
|
|
ExtraFlags = [running || maps:get(running, Opts, false)] ++ [send || maps:get(send, Opts, false)], |
|
|
|
[ |
|
|
|
erlang:trace(PidPortSpec, true, [call, procs, timestamp, arity, return_to, set_on_spawn, {tracer, tpTracer, TracerState} | ExtraFlags]) |
|
|
|
|| PidPortSpec <- Scope |
|
|
|
], |
|
|
|
trace_input(Tail, TracerState, Opts); |
|
|
|
trace_input([Mod | Tail], TracerState, Opts) when is_atom(Mod) -> |
|
|
|
MatchSpec = case Opts of |
|
|
|
#{process_dump := true} -> [{'_', [], [{message, {process_dump}}]}]; |
|
|
|
_ -> true |
|
|
|
end, |
|
|
|
MatchSpec = |
|
|
|
case Opts of |
|
|
|
#{process_dump := true} -> |
|
|
|
[{'_', [], [{message, {process_dump}}]}]; |
|
|
|
_ -> |
|
|
|
true |
|
|
|
end, |
|
|
|
%% The module must be loaded before we attempt to trace it. |
|
|
|
_ = code:ensure_loaded(Mod), |
|
|
|
_ = erlang:trace_pattern({Mod, '_', '_'}, MatchSpec, [local]), |
|
|
@ -127,4 +127,4 @@ stop() -> |
|
|
|
%% NIF does cancel traces when tracers go away, but |
|
|
|
%% better make sure. |
|
|
|
stop(PoolID) -> |
|
|
|
supervisor:terminate_child(looking_glass_sup, PoolID). |
|
|
|
supervisor:terminate_child(eTpf_sup, PoolID). |