Skip to content
Permalink
Browse files
add trace to pid other than group_leader()
  • Loading branch information
djnym committed Aug 6, 2015
1 parent e209456 commit 08d2ae3296daef0c98b3c3e2924b81873236536a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
@@ -32,6 +32,8 @@ all stable changes of the first version of Recon.
`recon:proc_window`.
- Fix doc typos
- Fix potential race condition on waiting for death of tracing process
- Add an option which allows sending tracing output somewhere other than
group_leader().
- 2.2.1
- Fixing type specs for `recon:port_types/0` and `recon_lib:count/1`,
thanks to @lucafavatella
@@ -152,6 +152,20 @@
%%% In case the operator is tracing from a remote shell which gets
%%% disconnected, the links between the shell and the tracer should make it
%%% so tracing is automatically turned off once you disconnect.
%%%
%%% If sending output to the Group Leader is not desired, you may specify
%%% a different pid() via the option `output' in the {@link calls/3} function.
%%% For instance to write the traces to a file you can do something like
%%%
%%% 1> {ok, Dev} = file:open("/tmp/trace",[write]).
%%% 2> recon_trace:calls({queue, in, fun(_) -> return_trace() end}, 3, [{output, Dev}]).
%%% 1
%%% 3>
%%% Recon tracer rate limit tripped.
%%% 4> file:close(Dev).
%%%
%%% The only output still sent to the Group Leader is the rate limit being
%%% tripped, and any errors.
%%% @end
-module(recon_trace).

@@ -161,7 +175,7 @@
-export([format/1]).

%% Internal exports
-export([count_tracer/1, rate_tracer/2, formatter/4]).
-export([count_tracer/1, rate_tracer/2, formatter/5]).

-type matchspec() :: [{[term()], [term()], [term()]}].
-type shellfun() :: fun((_) -> term()).
@@ -177,6 +191,7 @@
| {args, args | arity} % default: args
%% match pattern options
| {scope, global | local} % default: global
| {output, pid()} % default: group_leader()
].

-type mod() :: '_' | module().
@@ -305,10 +320,12 @@ calls(Spec, Max, Opts) ->
calls({Mod, Fun, Args}, Max, Opts, FormatterFun) ->
calls([{Mod,Fun,Args}], Max, Opts, FormatterFun);
calls(TSpecs = [_|_], {Max, Time}, Opts, FormatterFun) ->
Pid = setup(rate_tracer, [Max, Time], FormatterFun),
OutputTo = validate_output_to (Opts),
Pid = setup(rate_tracer, [Max, Time], FormatterFun, OutputTo),
trace_calls(TSpecs, Pid, Opts);
calls(TSpecs = [_|_], Max, Opts, FormatterFun) ->
Pid = setup(count_tracer, [Max], FormatterFun),
OutputTo = validate_output_to (Opts),
Pid = setup(count_tracer, [Max], FormatterFun, OutputTo),
trace_calls(TSpecs, Pid, Opts).

%%%%%%%%%%%%%%%%%%%%%%%
@@ -345,11 +362,11 @@ rate_tracer(Max, Time, Count, Start) ->
end.

%% @private Formats traces to be output
formatter(Tracer, Parent, Ref, FormatterFun) ->
formatter(Tracer, Parent, Ref, FormatterFun, OutputTo) ->
process_flag(trap_exit, true),
link(Tracer),
Parent ! {Ref, linked},
formatter(Tracer, group_leader(), FormatterFun).
formatter(Tracer, OutputTo, FormatterFun).

formatter(Tracer, Leader, FormatterFun) ->
receive
@@ -370,12 +387,12 @@ formatter(Tracer, Leader, FormatterFun) ->

%% starts the tracer and formatter processes, and
%% cleans them up before each call.
setup(TracerFun, TracerArgs, FormatterFun) ->
setup(TracerFun, TracerArgs, FormatterFun, OutputTo) ->
clear(),
Ref = make_ref(),
Tracer = spawn_link(?MODULE, TracerFun, TracerArgs),
register(recon_trace_tracer, Tracer),
Format = spawn(?MODULE, formatter, [Tracer, self(), Ref, FormatterFun]),
Format = spawn(?MODULE, formatter, [Tracer, self(), Ref, FormatterFun, OutputTo]),
register(recon_trace_formatter, Format),
receive
{Ref, linked} -> Tracer
@@ -449,6 +466,13 @@ validate_tspec(Mod, Fun, Args) ->
_ when Args >= 0, Args =< 255 -> {Args, true}
end.

validate_output_to(Opts) ->
OutputTo = proplists:get_value(output, Opts, undefined),
case OutputTo of
P when is_pid(OutputTo) -> P;
_ -> group_leader()
end.

%%%%%%%%%%%%%%%%%%%%%%%%
%%% TRACE FORMATTING %%%
%%%%%%%%%%%%%%%%%%%%%%%%

0 comments on commit 08d2ae3

Please sign in to comment.