File 0964-Add-missing-specs-for-et.patch of Package erlang
From 8a16f3b50fd39d36e5e59214e0a399b983ad0a63 Mon Sep 17 00:00:00 2001
From: Dan Gudmundsson <dgud@erlang.org>
Date: Fri, 5 Jan 2024 15:30:52 +0100
Subject: [PATCH 4/4] Add missing specs for et
---
lib/et/src/et.erl | 37 ++++++++++
lib/et/src/et_collector.erl | 136 +++++++++++++++++++++++++++++++-----
lib/et/src/et_selector.erl | 26 ++++++-
lib/et/src/et_viewer.erl | 39 +++++++++--
4 files changed, 214 insertions(+), 24 deletions(-)
diff --git a/lib/et/src/et.erl b/lib/et/src/et.erl
index b951439ef3..220a2c884b 100644
--- a/lib/et/src/et.erl
+++ b/lib/et/src/et.erl
@@ -89,6 +89,10 @@
trace_me/5, phone_home/5, report_event/5
]).
+
+-type actor() :: term().
+-type level() :: 0..100.
+
%%----------------------------------------------------------------------
%% Reports an event, such as a message
%%
@@ -126,26 +130,59 @@
%% Other events (termed actions) may be undirected and only have one actor.
%%----------------------------------------------------------------------
+-spec trace_me(DetailLevel, FromTo, Label, Contents) -> hopefully_traced when
+ DetailLevel :: level(),
+ FromTo :: actor(),
+ Label :: atom() | string() | term(),
+ Contents :: [{Key::term(), Value::term()}] | term().
trace_me(DetailLevel, FromTo, Label, Contents)
when is_integer(DetailLevel) ->
?MODULE:trace_me(DetailLevel, FromTo, FromTo, Label, Contents).
+-spec trace_me(DetailLevel, From, To, Label, Contents) -> hopefully_traced when
+ DetailLevel :: level(),
+ From :: actor(),
+ To :: actor(),
+ Label :: atom() | string() | term(),
+ Contents :: [{Key::term(), Value::term()}] | term().
trace_me(DetailLevel, _From, _To, _Label, _Contents)
when is_integer(DetailLevel) ->
hopefully_traced.
+-spec phone_home(DetailLevel, FromTo, Label, Contents) -> hopefully_traced when
+ DetailLevel :: level(),
+ FromTo :: actor(),
+ Label :: atom() | string() | term(),
+ Contents :: [{Key::term(), Value::term()}] | term().
phone_home(DetailLevel, FromTo, Label, Contents) ->
%% N.B External call
?MODULE:trace_me(DetailLevel, FromTo, FromTo, Label, Contents).
+-spec phone_home(DetailLevel, From, To, Label, Contents) -> hopefully_traced when
+ DetailLevel :: level(),
+ From :: actor(),
+ To :: actor(),
+ Label :: atom() | string() | term(),
+ Contents :: [{Key::term(), Value::term()}] | term().
phone_home(DetailLevel, From, To, Label, Contents) ->
%% N.B External call
?MODULE:trace_me(DetailLevel, From, To, Label, Contents).
+-spec report_event(DetailLevel, FromTo, Label, Contents) -> hopefully_traced when
+ DetailLevel :: level(),
+ FromTo :: actor(),
+ Label :: atom() | string() | term(),
+ Contents :: [{Key::term(), Value::term()}] | term().
report_event(DetailLevel, FromTo, Label, Contents) ->
%% N.B External call
?MODULE:trace_me(DetailLevel, FromTo, FromTo, Label, Contents).
+-spec report_event(DetailLevel, From, To, Label, Contents) -> hopefully_traced when
+ DetailLevel :: level(),
+ From :: actor(),
+ To :: actor(),
+ Label :: atom() | string() | term(),
+ Contents :: [{Key::term(), Value::term()}] | term().
report_event(DetailLevel, From, To, Label, Contents)
when is_integer(DetailLevel) ->
%% N.B External call
diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl
index 835bb380b8..058e7f473f 100644
--- a/lib/et/src/et_collector.erl
+++ b/lib/et/src/et_collector.erl
@@ -87,6 +87,44 @@
-record(trace_ts, {trace_ts, event_ts}).
-record(event_ts, {event_ts, trace_ts}).
+-type event() :: #event{}.
+-type table_handle() :: #table_handle{}.
+-type event_ts() :: #event_ts{}.
+-type trace_ts() :: #trace_ts{}.
+
+-type collector_fun() :: trace_filter_fun() | event_filter_fun().
+
+-type trace_filter_fun() :: fun((TraceData::tuple()) -> boolean() | {true, event()}).
+-type event_filter_fun() :: fun((Event::event()) -> boolean() | {true, event()}).
+
+-type dbg_match_spec() :: [tuple()]. %% See dbg match specs
+-type dbg_trace_type() :: ip | file | follow_file. %% See dbg:trace_client
+-type dbg_trace_parameters() :: file:filename() | integer() | {string(), integer()}. %% See dbg:trace_client
+
+-type ets_match_object_pattern() :: term(). %% See ets:match_object()
+
+-type level() :: 0..100.
+
+-type option()::
+ {parent_pid, pid() | undefined} |
+ {event_order, trace_ts | event_ts} |
+ {dict_insert, {filter, all}, collector_fun()} |
+ {dict_insert, {filter, EventFilterName::atom()}, event_filter_fun()} |
+ {dict_insert, {subscriber, pid()}, Val::term()} |
+ {dict_insert, Key::term(), Val::term()} |
+ {dict_delete, Key::term()} |
+ {trace_client, {event_file, file:filename()} |
+ {dbg_trace_type(), dbg_trace_parameters()}} |
+ {trace_global, boolean()} |
+ {trace_pattern, {module() | undefined, Level::level() | dbg_match_spec()} |
+ undefined} |
+ {trace_port, integer()} |
+ {trace_max_queue, integer()}.
+
+-type actor() :: term().
+
+-export_type([option/0]).
+
%%%----------------------------------------------------------------------
%%% Client side
%%%----------------------------------------------------------------------
@@ -163,7 +201,8 @@
%% CollectorPid = pid()
%% Reason = term()
%%----------------------------------------------------------------------
-
+-spec start_link(Options) -> {ok, Pid::pid()} | {error, term()} when
+ Options :: [option()].
start_link(Options) ->
case parse_opt(Options, default_state(), [], []) of
{ok, S, Dict2, Clients} ->
@@ -266,7 +305,7 @@ start_clients(CollectorPid, []) ->
%%
%% CollectorPid = pid()
%%----------------------------------------------------------------------
-
+-spec stop(CollectorPid::pid()) -> ok.
stop(CollectorPid) ->
call(CollectorPid, stop).
@@ -295,7 +334,10 @@ stop(CollectorPid) ->
%%
%% The options defaults to existing, write and keep.
%%----------------------------------------------------------------------
-
+-spec save_event_file(CollectorPid, FileName, [Option]) -> ok | {error, term()} when
+ CollectorPid :: pid(),
+ FileName :: file:filename(),
+ Option :: existing | write | append | keep | clear.
save_event_file(CollectorPid, FileName, Options) ->
call(CollectorPid, {save_event_file, FileName, Options}).
@@ -309,7 +351,10 @@ save_event_file(CollectorPid, FileName, Options) ->
%% BadBytes = integer(X) where X >= 0
%% Reason = term()
%%----------------------------------------------------------------------
-
+-spec load_event_file(CollectorPid, FileName) ->{ok, BadBytes} when
+ CollectorPid :: pid(),
+ FileName :: file:filename(),
+ BadBytes :: pos_integer().
load_event_file(CollectorPid, FileName) ->
Fd = make_ref(),
Args = [{file, FileName}, {name, Fd}, {repair, true}, {mode, read_only}],
@@ -359,6 +404,11 @@ do_load_event_file(Fun, Fd, Cont, Acc, FileName, BadBytes) ->
%% Returns: {ok, Continuation} | exit(Reason)
%%----------------------------------------------------------------------
+-spec report(Handle, TraceOrEvent) -> {ok, Continuation} when
+ Handle :: table_handle() | CollectorPid::pid(),
+ TraceOrEvent :: event() | TraceData | end_of_trace,
+ TraceData :: tuple(),
+ Continuation :: table_handle().
report(CollectorPid, TraceOrEvent) when is_pid(CollectorPid) ->
case get_table_handle(CollectorPid) of
{ok, TH} when is_record(TH, table_handle) ->
@@ -411,9 +461,24 @@ report(TH, TraceOrEvent) when is_record(TH, table_handle) ->
report(_, Bad) ->
exit({bad_event, Bad}).
+-spec report_event(CollectorPid, DetailLevel, FromTo, Label, Contents) -> {ok, Continuation} when
+ CollectorPid :: pid(),
+ DetailLevel :: level(),
+ FromTo :: actor(),
+ Label :: term(),
+ Contents :: [{Key::term(), Value::term()}] | term(),
+ Continuation :: table_handle().
report_event(CollectorPid, DetailLevel, FromTo, Label, Contents) ->
report_event(CollectorPid, DetailLevel, FromTo, FromTo, Label, Contents).
+-spec report_event(CollectorPid, DetailLevel, From, To, Label, Contents) -> {ok, Continuation} when
+ CollectorPid :: pid(),
+ DetailLevel :: level(),
+ From :: actor(),
+ To :: actor(),
+ Label :: term(),
+ Contents :: [{Key::term(), Value::term()}] | term(),
+ Continuation :: table_handle().
report_event(CollectorPid, DetailLevel, From, To, Label, Contents)
when is_integer(DetailLevel),
DetailLevel >= ?detail_level_min,
@@ -438,6 +503,10 @@ report_event(CollectorPid, DetailLevel, From, To, Label, Contents)
%% Key = record(event_ts) | record(trace_ts)
%%----------------------------------------------------------------------
+-spec make_key(Handle, Stuff) -> Key when
+ Handle :: table_handle() | trace_ts | event_ts,
+ Stuff :: event() | Key,
+ Key :: event_ts() | trace_ts().
make_key(TH, Stuff) when is_record(TH, table_handle) ->
make_key(TH#table_handle.event_order, Stuff);
make_key(trace_ts, Stuff) ->
@@ -490,7 +559,7 @@ get_table_handle(CollectorPid) when is_pid(CollectorPid) ->
%% CollectorPid = pid()
%% Reason = term()
%%----------------------------------------------------------------------
-
+-spec get_global_pid() -> CollectorPid :: pid().
get_global_pid() ->
case global:whereis_name(?MODULE) of
CollectorPid when is_pid(CollectorPid) ->
@@ -512,7 +581,10 @@ get_global_pid() ->
%% detail_level() = min | max | integer(X) when X =< 0, X >= 100
%% TracePattern = {report_module(), dbg_match_spec_match_spec()}
%%----------------------------------------------------------------------
-
+-spec change_pattern(CollectorPid, RawPattern) -> {old_pattern, TracePattern} when
+ CollectorPid :: pid(),
+ RawPattern :: {module(), min | max | level()},
+ TracePattern :: [{[term()] | '_' | atom(), [term()], [term()]}].
change_pattern(CollectorPid, RawPattern) ->
Pattern = et_selector:make_pattern(RawPattern),
call(CollectorPid, {change_pattern, Pattern}).
@@ -542,7 +614,11 @@ change_pattern(CollectorPid, RawPattern) ->
%% Key = term()
%% Val = term()
%%----------------------------------------------------------------------
-
+-spec dict_insert(CollectorPid, What, Value) -> ok when
+ CollectorPid :: pid(),
+ What :: {filter, atom()} | {subscriber, pid()} | Key,
+ Key :: term(),
+ Value :: collector_fun() | term().
dict_insert(CollectorPid, Key = {filter, Name}, Fun) ->
if
is_atom(Name), is_function(Fun) ->
@@ -569,14 +645,14 @@ dict_insert(CollectorPid, Key, Val) ->
%% Key = term()
%% Val = term()
%%----------------------------------------------------------------------
-
+-spec dict_lookup(CollectorPid::pid(), Key::term()) -> [Val::term()].
dict_lookup(CollectorPid, Key) ->
call(CollectorPid, {dict_lookup, Key}).
%%----------------------------------------------------------------------
-%% Ddict_delete(CollectorPid, Key) -> ok
+%% dict_delete(CollectorPid, Key) -> ok
%%
-%% elete a dictionary entry
+%% Delete a dictionary entry
%% and send a {et, {dict_delete, Key}} tuple
%% to all registered subscribers.
%%
@@ -591,7 +667,7 @@ dict_lookup(CollectorPid, Key) ->
%% SubscriberPid = pid()
%% Key = term()
%%----------------------------------------------------------------------
-
+-spec dict_delete(CollectorPid::pid(), Key::term()) -> ok.
dict_delete(CollectorPid, Key) ->
call(CollectorPid, {dict_delete, Key}).
@@ -608,7 +684,10 @@ dict_delete(CollectorPid, Key) ->
%% key() = term()
%% val() = term()
%%----------------------------------------------------------------------
-
+-spec dict_match(CollectorPid::pid(), {KeyPattern, ValPattern}) -> [Match] when
+ KeyPattern :: ets_match_object_pattern(),
+ ValPattern :: ets_match_object_pattern(),
+ Match :: {Key::term(), Val::term()}.
dict_match(CollectorPid, Pattern) ->
call(CollectorPid, {dict_match, Pattern}).
@@ -620,7 +699,7 @@ dict_match(CollectorPid, Pattern) ->
%% CollectorPid = pid()
%% Msg = term()
%%----------------------------------------------------------------------
-
+-spec multicast(CollectorPid :: pid(), Msg::term()) -> ok.
multicast(_CollectorPid, Msg = {dict_insert, _Key, _Val}) ->
exit({badarg, Msg});
multicast(_CollectorPid, Msg = {dict_delete, _Key}) ->
@@ -638,7 +717,10 @@ multicast(CollectorPid, Msg) ->
%% Parameters = dbg_trace_client_parameters()
%% Pid = dbg_trace_client_pid()
%%----------------------------------------------------------------------
-
+-spec start_trace_client(CollectorPid, Type, Parameter) -> file_loaded | {trace_client_pid, pid()} when
+ CollectorPid :: pid(),
+ Type :: event_file | dbg_trace_type(),
+ Parameter :: dbg_trace_parameters().
start_trace_client(CollectorPid, Type, FileName) when Type =:= event_file ->
load_event_file(CollectorPid, FileName);
start_trace_client(CollectorPid, Type, FileName) when Type =:= file ->
@@ -697,7 +779,15 @@ monitor_trace_port(CollectorPid, Parameters) ->
%%
%% Short for iterate/5.
%%----------------------------------------------------------------------
-
+-spec iterate(Handle, Prev, Limit) -> NewAcc when
+ Handle :: CollectorPid | table_handle(),
+ CollectorPid :: pid(),
+ Prev :: first | last | term(),
+ Limit :: Done | Forward | Backward,
+ Done :: 0,
+ Forward :: pos_integer(),
+ Backward :: neg_integer(),
+ NewAcc :: term().
iterate(Handle, Prev, Limit) ->
iterate(Handle, Prev, Limit, undefined, Prev).
@@ -720,7 +810,17 @@ iterate(Handle, Prev, Limit) ->
%% Fun = fun(Event, Acc) -> NewAcc
%% Acc = NewAcc = term()
%%----------------------------------------------------------------------
-
+-spec iterate(Handle, Prev, Limit, Fun, Acc) -> NewAcc when
+ Handle :: CollectorPid | table_handle(),
+ CollectorPid :: pid(),
+ Prev :: first | last | term(),
+ Limit :: Done | Forward | Backward,
+ Done :: 0,
+ Forward :: pos_integer() | 'infinity',
+ Backward :: neg_integer() | '-infinity',
+ Fun :: fun((event(), Acc) -> NewAcc) | undefined,
+ Acc :: term(),
+ NewAcc :: term().
iterate(_, _, Limit, _, Acc) when Limit =:= 0 ->
Acc;
iterate(CollectorPid, Prev, Limit, Fun, Acc) when is_pid(CollectorPid) ->
@@ -858,7 +958,9 @@ incr(Val, Incr) ->
%% collector_pid() = pid()
%% table_handle() = record(table_handle)
%%----------------------------------------------------------------------
-
+-spec clear_table(Handle) -> ok when
+ Handle :: CollectorPid | table_handle(),
+ CollectorPid :: pid().
clear_table(CollectorPid) when is_pid(CollectorPid) ->
call(CollectorPid, clear_table);
clear_table(TH) when is_record(TH, table_handle) ->
diff --git a/lib/et/src/et_selector.erl b/lib/et/src/et_selector.erl
index 18a7e66b1d..e83088d823 100644
--- a/lib/et/src/et_selector.erl
+++ b/lib/et/src/et_selector.erl
@@ -31,6 +31,10 @@
-include("../include/et.hrl").
+-type event() :: #event{}.
+
+-type level() :: 0..100.
+
%%----------------------------------------------------------------------
%% make_pattern(RawPattern) -> TracePattern
%%
@@ -46,7 +50,9 @@
%% max - maximum level of tracing (all calls to trace_me/4,5)
%% integer() - explicit detail level of tracing
%%----------------------------------------------------------------------
-
+-spec make_pattern({Mod::module(), RawPattern}) -> {Mod::module(), TracePattern} when
+ RawPattern :: level(),
+ TracePattern :: [{[term()] | '_' | atom(), [term()], [term()]}].
make_pattern(undefined) ->
{undefined, undefined};
make_pattern({Mod, Pattern}) when is_atom(Mod) ->
@@ -93,7 +99,11 @@ make_pattern({Mod, Pattern}) when is_atom(Mod) ->
%% Other match specs activates tracing of calls to trace_me/4,5
%% accordingly with erlang:trace_pattern/2.
%%----------------------------------------------------------------------
-
+-spec change_pattern({Mod::module(), Pattern}) -> ok when
+ Pattern :: DetailLevel | TracePattern | EmptyTracePattern,
+ DetailLevel :: level(),
+ TracePattern :: [{[term()] | '_' | atom(), [term()], [term()]}],
+ EmptyTracePattern :: [].
change_pattern({Mod, Pattern}) when is_atom(Mod) ->
MFA = {Mod, trace_me, 5},
case Pattern of
@@ -176,7 +186,17 @@ error_to_exit({ok, _Res}) ->
%% false - means that the trace data is uninteresting and
%% should be dropped
%%----------------------------------------------------------------------
-
+-spec parse_event(Mod, ValidTraceData) -> boolean | {true, event()} when
+ Mod :: module(),
+ ValidTraceData :: ErlangTraceData | event(),
+ ErlangTraceData ::
+ {trace, pid(), atom(), term()} |
+ {trace, pid(), atom(), term(), term()} |
+ {trace_ts, pid(), atom(), term(), TS::{integer(), integer(), integer()}} |
+ {trace_ts, pid(), atom(), term(), term(), TS::{integer(), integer(), integer()}} |
+ {seq_trace, atom(), term()} |
+ {seq_trace, atom(), term(), TS::{integer(), integer(), integer()}} |
+ {drop, integer()}.
parse_event(_Mod, E) when is_record(E, event) ->
true;
parse_event(Mod, Trace) ->
diff --git a/lib/et/src/et_viewer.erl b/lib/et/src/et_viewer.erl
index 3928764c7f..d3e2c2f409 100644
--- a/lib/et/src/et_viewer.erl
+++ b/lib/et/src/et_viewer.erl
@@ -40,6 +40,24 @@
-define(unknown, "UNKNOWN").
+-type actors() :: [term()].
+-type first_key() :: term().
+-type option() ::
+ {title, string()} |
+ {detail_level, 0..100} |
+ {is_suspended, boolean()} |
+ {scale, integer()} |
+ {width, integer()} |
+ {height, integer()}|
+ {collector_pid, pid() | undefined} |
+ {active_filter, atom()} |
+ {max_events, integer() | undefined} |
+ {max_actors, integer() | undefined} |
+ {actors, actors()} |
+ {first_event, first_key()} |
+ {hide_unknown, boolean()} |
+ {hide_actions, boolean()} |
+ {display_mode, all | {search_actors, forward | reverse, first_key(), actors()}}.
%%%----------------------------------------------------------------------
%%% Client side
@@ -55,7 +73,7 @@
%% ViewerPid = pid()
%% Reason = term()
%%----------------------------------------------------------------------
-
+-spec file(FileName::file:filename()) -> {ok, pid()} | {error, term()}.
file(FileName) ->
start_link([{trace_client, {file, FileName}}], default).
@@ -70,18 +88,25 @@ file(FileName) ->
%% processes are unlinked from the calling process.
%%----------------------------------------------------------------------
+-spec start() -> {ok, pid()} | {error, term()}.
start() ->
start([{trace_global, true}], default).
%%----------------------------------------------------------------------
%% start(Options) -> {ok, ViewerPid} | {error, Reason}
%%----------------------------------------------------------------------
-
+-spec start(GUIorOptions) -> {ok, Viewer::pid()} | {error, term()} when
+ GUIorOptions :: wx | default | Options,
+ Options :: [option() | et_collector:option()].
start(GUI) when GUI =:= wx; GUI =:= default ->
start_link([{trace_global, true}], GUI);
start(Options) ->
start_link([{parent_pid, undefined} | Options], default).
+-spec start(Options, GUI) -> {ok, Viewer::pid()} | {error, term()} when
+ GUI :: wx | default,
+ Options :: [option() | et_collector:option()].
+
start(Options, GUI) ->
start_link([{parent_pid, undefined} | Options], GUI).
@@ -139,12 +164,17 @@ start(Options, GUI) ->
%% A filter_fun() takes an event record as sole argument
%% and returns false | true | {true, NewEvent}.
%%----------------------------------------------------------------------
-
+-spec start_link(GUIorOptions) -> {ok, Viewer::pid()} | {error, term()} when
+ GUIorOptions :: wx | default | Options,
+ Options :: [option() | et_collector:option()].
start_link(GUI) when GUI =:= wx; GUI =:= default ->
start_link([{trace_global, true}], GUI);
start_link(Options) ->
start_link(Options, default).
+-spec start_link(Options, GUI) -> {ok, Viewer::pid()} | {error, term()} when
+ GUI :: wx | default,
+ Options :: [option() | et_collector:option()].
start_link(Options, GUI) ->
case GUI of
wx ->
@@ -155,6 +185,7 @@ start_link(Options, GUI) ->
which_gui() -> wx.
+-spec get_collector_pid(ViewerPid::pid()) -> pid().
get_collector_pid(ViewerPid) ->
call(ViewerPid, get_collector_pid).
@@ -165,7 +196,7 @@ get_collector_pid(ViewerPid) ->
%%
%% ViewerPid = pid()
%%----------------------------------------------------------------------
-
+-spec stop(ViewerPid::pid()) -> ok.
stop(ViewerPid) ->
call(ViewerPid, stop).
--
2.35.3