Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
60e510c
Add test_statem module for state machine testing functionality
Apr 15, 2025
c94fef0
Add a fake registration module for testing and update recon_trace_SUITE
flmath Apr 18, 2025
cb57204
Refactor recon_trace_SUITE to improve test case structure and logging…
flmath Apr 19, 2025
eaeb820
cleaning up and describing recon_trace_SUITE
flmath Apr 19, 2025
32d3781
frame for recon trace use dbg development
flmath Apr 28, 2025
4f5f68f
dirty version of dbg use feature
flmath May 1, 2025
217bece
make dummy_basic_test in recon_trace_use_dbg_SUITE.erl work wih use_dbg.
flmath May 4, 2025
af207d1
tempplorary before code removal
flmath May 10, 2025
a6a966e
both basic pattern and fun works
flmath May 11, 2025
0e6fe50
use matching lists instead functions for use_dbg
flmath May 11, 2025
0edf4df
use_dbg support for arity match
flmath May 12, 2025
082df0b
use_dbg rate trace limit
flmath May 12, 2025
74771bb
use_dgb added support for scope and PidSpecs
flmath May 13, 2025
9c30798
Enhance tracing functionality by adding arity handling and improving …
flmath May 16, 2025
48ce054
all legacy type testcase passed for use_dbg
flmath May 17, 2025
ecfc5cd
Add support for new tracing functions in recon_trace and recon_trace_…
flmath May 17, 2025
ad21953
Refactor tracing calls to unify recon_trace and recon_trace_use_dbg f…
flmath May 17, 2025
d3619a6
Enhance tracing functionality by adding clear support for recon_trace…
flmath May 18, 2025
d07bbab
Enhance tracing functionality by adding return_to option and related …
flmath May 18, 2025
7a62799
Add suppress print for recon_trace_use_dbg
flmath May 18, 2025
b8dc7d9
Enhance documentation and test cases for recon_trace_use_dbg module, …
flmath May 18, 2025
84946c2
Update author information and documentation in test suites for clarit…
flmath May 18, 2025
60b16bd
Add print_accutator function and enhance rate limiting in recon_trace…
flmath Jul 1, 2025
cc705bf
Restrict tracing functionality in recon_trace_use_dbg module, now it …
flmath Jul 2, 2025
c692310
Fix pattern matching in pass_all function and adjust count_tracer con…
flmath Jul 2, 2025
67d627c
trace_function_type to introduce silent_fun_to_ms for improved shell_…
flmath Jul 3, 2025
a1e3fb3
Refactor calls_dbg to handle multiple PIDs and add trace_multi_pid_te…
flmath Jul 4, 2025
583ca72
Enhance print_accutator output format and update trace_custom_value_p…
flmath Jul 4, 2025
4348916
fixing problems related to OTP24
flmath Jul 4, 2025
7f41ff4
Remove unused rebar.lock and recon.mermaid files
flmath Jul 5, 2025
c70b87b
Fix print actuator naming and improve unregister logic in recon_trace…
flmath Jul 5, 2025
58cd927
Implement plugin_tracker module and enhance recon_trace_use_dbg with …
flmath Aug 20, 2025
a8ca34c
Merge branch 'ferd:master' into master
flmath Aug 20, 2025
fa6131b
Add recon_plugins module with type definitions and callbacks
flmath Aug 20, 2025
b96dfac
Remove commented-out test case for binary patterns in recon_trace_use…
flmath Aug 23, 2025
75371fb
Fix formatting in plugin_tracker and update test case for recon_trace…
flmath Aug 23, 2025
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
1 change: 0 additions & 1 deletion rebar.lock

This file was deleted.

99 changes: 99 additions & 0 deletions src/plugins/plugin_tracker.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
-module(plugin_tracker).
-behaviour(recon_plugins).

-export([filter_fun/5, start_value/2, is_plugin/0]).
-import(recon_trace, [formatter/5, validate_opts/1, trace_to_io/2,
format/1, extract_info/1, clear/0]).

is_plugin() ->
true.

filter_fun(TSpecs, Boundaries, IoServer, Formatter, _Opts) ->
generate_pattern_filter(Boundaries, TSpecs, IoServer, Formatter).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% GENERATE PATTERN FILTER %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
generate_pattern_filter(TSpecs, {Max, Time}, IoServer, Formatter) ->
clear(),
rate_tracer({Max, Time}, TSpecs, IoServer, Formatter);
generate_pattern_filter(TSpecs, Max, IoServer, Formatter) ->
clear(),
count_tracer(Max, TSpecs, IoServer, Formatter).

count_tracer(Max, _TSpecs, IoServer, Formatter) ->
fun
(_Trace, {_, _, N}) when N >= Max ->
IoServer ! rate_limit_tripped, clear();
(Trace, {TSpecs, Session,N}) when (N < Max) and is_tuple(Trace) ->
%% Type = element(1, Trace),
handle_trace(Trace, N, TSpecs, IoServer, Formatter, Session)
end.

rate_tracer({_Max, _Time}, _TSpecs, _IoServer, _Formatter) ->
io:format("Rate tracer is not supported for module: ~p~n", [?MODULE]).

handle_trace(_, _, [], IoServer, _, _) ->
IoServer ! rate_limit_tripped, clear();
handle_trace(Trace, N, [TSpec | TSpecRest] = TSpecs, IoServer, Formatter, Session) ->
Print = filter_call(Trace, TSpec, Session),
case Print of
reject -> {TSpecs, Session, N};
{print, Value, NewSession} ->
IoServer ! {print_value, Value},
{TSpecRest, NewSession, N+1};
{print, NewSession} ->
case Formatter(Trace) of
"" -> ok;
Formatted -> IoServer ! {msg, Formatted}
end,
{TSpecRest, NewSession, N+1};
_ -> {TSpecs, Session, N}
end.


filter_call(TraceMsg, {M, F, PatternFun}, Session) ->
case extract_info(TraceMsg) of
{call, _, _, [{TraceM,TraceF, Args}]} ->
test_match(M, F, TraceM, TraceF, Args, PatternFun, Session);
{call, _, _, [{TraceM, TraceF, Args}, _Msg]} ->
test_match(M, F, TraceM, TraceF, Args, PatternFun, Session);
%% if the trace is not a call, we just print it
_ -> {print, Session}
end.

test_match(M, F, TraceM, TraceF, Args, PatternFun, Session) ->
Match =
case {M==TraceM, ((F=='_') or (F==TraceF)), PatternFun} of
{true, true, '_'} -> true;
{true, true, _} -> check;
_ -> false
end,

case Match of
true -> {print, Session};
false -> reject;
check ->
try erlang:apply(PatternFun, [Args, Session]) of
suppress -> reject;
print -> {print, Session};
{print, Value} -> {print, Value, Session};
{print_session, NewSession} -> {print, maps:merge(Session, NewSession)};
{print_session, Value, NewSession} -> {print, Value, maps:merge(Session, NewSession)};
_ -> reject
catch
error:function_clause ->
reject;
error:arity_no_match ->
reject;
error:_E ->
reject
end
end.

%%% Start value for the dbg tracer process state
start_value(_, {_, _}) ->
{0, undefined, 0};
start_value(Specs, _Max) ->
{Specs, #{}, 0}.

21 changes: 21 additions & 0 deletions src/recon_plugins.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
%%% @author <[email protected]>
%%% [https://flmath.github.io]
%%% @doc
%%% `recon_trace_use_dbg' is a module that allows API of recon use dbg module
%%% The added value of this solution is more flexibility in the pattern matching
%%% you can pattern match any structure you BEAM can put into function guard.
-module(recon_plugins).
%% API

-type tspec() :: recon_trace_use_dbg:tspec().
-type device() :: atom() | pid() | standard_io | standard_error | user.
-type property() :: atom() | tuple().
-type proplist() :: [property()].
-type init() :: recon_trace_use_dbg:max_traces().
-type matchspecs() :: recon_trace_use_dbg:matchspecs().

-type filter_fun_type() :: fun((tspec() | [tspec()], init()) -> init()).

-callback filter_fun(matchspecs(), init(), device(), pid(), proplist()) -> filter_fun_type().
-callback is_plugin() -> boolean().
-callback start_value(matchspecs(), init()) -> {matchspecs(), map(), init()}.
34 changes: 27 additions & 7 deletions src/recon_trace.erl
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@
%% Internal exports
-export([count_tracer/1, rate_tracer/2, formatter/5, format_trace_output/1, format_trace_output/2]).

%% For use_dbg feature
-export([trace_to_io/2, extract_info/1, validate_opts/1, fun_to_ms/1]).

-type matchspec() :: [{[term()] | '_', [term()], [term()]}].
-type shellfun() :: fun((_) -> term()).
-type formatterfun() :: fun((_) -> iodata()).
Expand Down Expand Up @@ -228,6 +231,13 @@ clear() ->
erlang:trace_pattern({'_','_','_'}, false, []), % unsets global
maybe_kill(recon_trace_tracer),
maybe_kill(recon_trace_formatter),

%% for recon_trace_use_dbg
maybe_kill(recon_trace_tracer),
catch unregister(recon_trace_tracer),
dbg:p(all,clear),
dbg:ctp('_'),
dbg:stop(),
ok.

%% @equiv calls({Mod, Fun, Args}, Max, [])
Expand Down Expand Up @@ -336,11 +346,18 @@ calls(TSpecs = [_|_], Max) ->

calls({Mod, Fun, Args}, Max, Opts) ->
calls([{Mod,Fun,Args}], Max, Opts);
calls(TSpecs = [_|_], {Max, Time}, Opts) ->

calls(TSpecs = [_|_], Boundaries, Opts) ->
case proplists:get_bool(use_dbg, Opts) of
true -> recon_trace_use_dbg:calls_dbg(TSpecs, Boundaries, Opts);
false -> spec_calls(TSpecs, Boundaries, Opts)
end.

spec_calls(TSpecs = [_|_], {Max, Time}, Opts) ->
Pid = setup(rate_tracer, [Max, Time],
validate_formatter(Opts), validate_io_server(Opts)),
trace_calls(TSpecs, Pid, Opts);
calls(TSpecs = [_|_], Max, Opts) ->
spec_calls(TSpecs = [_|_], Max, Opts) ->
Pid = setup(count_tracer, [Max],
validate_formatter(Opts), validate_io_server(Opts)),
trace_calls(TSpecs, Pid, Opts).
Expand Down Expand Up @@ -486,7 +503,7 @@ validate_tspec(Mod, Fun, Args) when is_function(Args) ->
validate_tspec(Mod, Fun, return_trace) ->
validate_tspec(Mod, Fun, [{'_', [], [{return_trace}]}]);
validate_tspec(Mod, Fun, Args) ->
BannedMods = ['_', ?MODULE, io, lists],
BannedMods = ['_', ?MODULE, io, lists, recon_trace_use_dbg],
%% The banned mod check can be bypassed by using
%% match specs if you really feel like being dumb.
case {lists:member(Mod, BannedMods), Args} of
Expand Down Expand Up @@ -515,7 +532,12 @@ validate_io_server(Opts) ->
%% Thanks Geoff Cant for the foundations for this.
format(TraceMsg) ->
{Type, Pid, {Hour,Min,Sec}, TraceInfo} = extract_info(TraceMsg),
{FormatStr, FormatArgs} = case {Type, TraceInfo} of
{FormatStr, FormatArgs} = trace_to_io(Type, TraceInfo),
io_lib:format("~n~p:~p:~9.6.0f ~p " ++ FormatStr ++ "~n",
[Hour, Min, Sec, Pid] ++ FormatArgs).

trace_to_io(Type, TraceInfo) ->
case {Type, TraceInfo} of
%% {trace, Pid, 'receive', Msg}
{'receive', [Msg]} ->
{"< ~p", [Msg]};
Expand Down Expand Up @@ -590,9 +612,7 @@ format(TraceMsg) ->
[HeapSize + OldHeapSize + MbufSize]};
_ ->
{"unknown trace type ~p -- ~p", [Type, TraceInfo]}
end,
io_lib:format("~n~p:~p:~9.6.0f ~p " ++ FormatStr ++ "~n",
[Hour, Min, Sec, Pid] ++ FormatArgs).
end.

extract_info(TraceMsg) ->
case tuple_to_list(TraceMsg) of
Expand Down
Loading