diff options
Diffstat (limited to 'lib/et/examples/et_demo.erl')
-rw-r--r-- | lib/et/examples/et_demo.erl | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/lib/et/examples/et_demo.erl b/lib/et/examples/et_demo.erl new file mode 100644 index 0000000000..57e7e77246 --- /dev/null +++ b/lib/et/examples/et_demo.erl @@ -0,0 +1,351 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% et_demo.erl - Provide some event trace filter examples. +%%---------------------------------------------------------------------- + +-module(et_demo). + +-export([ + sim_trans/0, + mgr_actors/1, + live_trans/0, + start/0, + start/1, + filters/0, + trace_mnesia/0 + ]). + +-include_lib("et/include/et.hrl"). + +%%---------------------------------------------------------------------- + +%sim_trans +sim_trans() -> + Options = [{dict_insert, {filter, mgr_actors}, fun mgr_actors/1}], + {ok, Viewer} = et_viewer:start_link(Options), + Collector = et_viewer:get_collector_pid(Viewer), + et_collector:report_event(Collector, 60, my_shell, mnesia_tm, start_outer, + "Start outer transaction"), + et_collector:report_event(Collector, 40, mnesia_tm, my_shell, new_tid, + "New transaction id is 4711"), + et_collector:report_event(Collector, 20, my_shell, mnesia_locker, try_write_lock, + "Acquire write lock for {my_tab, key}"), + et_collector:report_event(Collector, 10, mnesia_locker, my_shell, granted, + "You got the write lock for {my_tab, key}"), + et_collector:report_event(Collector, 60, my_shell, do_commit, + "Perform transaction commit"), + et_collector:report_event(Collector, 40, my_shell, mnesia_locker, release_tid, + "Release all locks for transaction 4711"), + et_collector:report_event(Collector, 60, my_shell, mnesia_tm, delete_transaction, + "End of outer transaction"), + et_collector:report_event(Collector, 20, my_shell, end_outer, + "Transaction returned {atomic, ok}"). +%sim_trans + +%mgr_actors +mgr_actors(E) when record(E, event) -> + Actor = fun(A) -> + case A of + mnesia_tm -> trans_mgr; + mnesia_locker -> lock_mgr; + _ -> A + end + end, + {true, E#event{from = Actor(E#event.from), + to = Actor(E#event.to), + contents = [{orig_from, E#event.from}, + {orig_to, E#event.to}, + {orig_contents, E#event.contents}]}}. +%mgr_actors + +%%---------------------------------------------------------------------- + +%start +start() -> + start([]). + +start(ExtraOptions) -> + Options = [{trace_global, true}, + {parent_pid, undefined}, + {max_actors, infinity}, + {max_events, 1000}, + {active_filter, module_as_actor}], + et_viewer:start_link(filters() ++ Options ++ ExtraOptions). +%start + +%%---------------------------------------------------------------------- + +%live_trans +live_trans() -> + et_demo:start([{title, "Mnesia tracer"}, + {hide_actions, true}, + {active_filter, named_process_info_nolink}]), + mnesia:start(), + mnesia:create_table(my_tab, [{ram_copies, [node()]}]), + et_demo:trace_mnesia(), + register(my_shell, self()), + + mnesia:transaction(fun() -> mnesia:write({my_tab, key, val}) end). +%live_trans + +%%---------------------------------------------------------------------- + +%trace_mnesia +trace_mnesia() -> + Modules = mnesia:ms(), + Spec = [{message, {caller}}, {return_trace}], + Flags = [send, 'receive', procs, timestamp], + dbg:p(all, [call, timestamp]), + [dbg:tpl(M, [{'_', [], Spec}]) || M <- Modules], + LocallyRunningServers = [M || M <- Modules, whereis(M) /= undefined], + [dbg:p(whereis(RS), Flags) || RS <- LocallyRunningServers], + dbg:p(self(), Flags), + LocallyRunningServers. +%trace_mnesia + +%%---------------------------------------------------------------------- +%% Filter funs returns false, true or {true, NewEvent} +%%---------------------------------------------------------------------- + +%filters +filters() -> + [{dict_insert, {filter, module_as_actor}, + fun module_as_actor/1}, + {dict_insert, {filter, plain_process_info}, + fun plain_process_info/1}, + {dict_insert, {filter, plain_process_info_nolink}, + fun plain_process_info_nolink/1}, + {dict_insert, {filter, named_process_info}, + fun named_process_info/1}, + {dict_insert, {filter, named_process_info_nolink}, + fun named_process_info_nolink/1}, + {dict_insert, {filter, node_process_info}, + fun node_process_info/1}, + {dict_insert, {filter, node_process_info_nolink}, + fun node_process_info_nolink/1}, + {dict_insert, {filter, application_as_actor}, + fun application_as_actor/1} + ]. +%filters + +%module_as_actor +module_as_actor(E) when record(E, event) -> + case lists:keysearch(mfa, 1, E#event.contents) of + {value, {mfa, {M, F, _A}}} -> + case lists:keysearch(pam_result, 1, E#event.contents) of + {value, {pam_result, {M2, _F2, _A2}}} -> + {true, E#event{label = F, from = M2, to = M}}; + _ -> + {true, E#event{label = F, from = M, to = M}} + end; + _ -> + false + end. +%module_as_actor + +%%---------------------------------------------------------------------- + +%plain_process_info +plain_process_info(E) when record(E, event) -> + case E#event.label of + send -> true; + send_to_non_existing_process -> true; + 'receive' -> true; + spawn -> true; + exit -> true; + link -> true; + unlink -> true; + getting_linked -> true; + {seq_send, _Label} -> true; + {seq_receive, _Label} -> true; + {seq_print, _Label} -> true; + {drop, _N} -> true; + _ -> false + end. +%plain_process_info + +%plain_process_info_nolink +plain_process_info_nolink(E) when record(E, event) -> + (E#event.label /= link) and + (E#event.label /= unlink) and + (E#event.label /= getting_linked) and + plain_process_info(E). +%plain_process_info_nolink + +%%---------------------------------------------------------------------- + +named_process_info(E) when record(E, event) -> + case plain_process_info(E) of + true -> + {true, E#event{to = pid_to_name(E#event.to), + from = pid_to_name(E#event.from), + label = msg_to_label(E)}}; + false -> + false + end. + +named_process_info_nolink(E) when record(E, event) -> + case plain_process_info_nolink(E) of + true -> + {true, E#event{to = pid_to_name(E#event.to), + from = pid_to_name(E#event.from), + label = msg_to_label(E)}}; + false -> + false + end. + +pid_to_name(Pid) when pid(Pid) -> + case process_info(Pid, registered_name) of + {registered_name, Name} -> + Name; + _ -> + Pid + end; +pid_to_name({Name, Node}) when Node == node() -> + Name; +pid_to_name(Other) -> + Other. + +%%---------------------------------------------------------------------- + +node_process_info(E) when record(E, event) -> + case plain_process_info(E) of + true -> + {true, E#event{to = pid_to_node(E#event.to), + from = pid_to_node(E#event.from), + label = msg_to_label(E)}}; + false -> + false + end. +node_process_info_nolink(E) when record(E, event) -> + case plain_process_info_nolink(E) of + true -> + {true, E#event{to = pid_to_node(E#event.to), + from = pid_to_node(E#event.from), + label = msg_to_label(E)}}; + false -> + false + end. + +pid_to_node(Pid) when pid(Pid) -> + node(Pid); +pid_to_node(Name) when atom(Name) -> + node(); +pid_to_node({_Name, Node}) when atom(Node) -> + Node. + +%%---------------------------------------------------------------------- + +application_as_actor(E) when record(E, event) -> + {true, E#event{to = pid_to_application(E#event.to), + from = pid_to_application(E#event.from), + label = msg_to_label(E)}}. + +pid_to_application(Pid) when pid(Pid) -> + case application:get_application(Pid) of + {ok, Name} -> + Name; + _ -> + "UNKNOWN" + end. + +%%---------------------------------------------------------------------- + +msg_to_label(E) when record(E, event) -> + case lists:keysearch(msg, 1, E#event.contents) of + {value, {msg, Msg}} -> + mnesia_msg_to_label(Msg, E#event.label); + false -> + E#event.label + end. + +mnesia_msg_to_label(Msg, Label) -> + case Msg of + {mnesia_tm, _Node, Reply} -> + case Reply of + ok -> ok; + store_erased -> store_erased; + unblocked -> unblocked; + {_From, _Ref, start_outer} -> start_outer; + {aborted, _Tid} -> aborted; + {committed, _Tid} -> committed; + {dirty_res, _Res} -> dirty_res; + {error, _Reason} -> error; + {info, _Part, _Coord} -> info; + {mnesia_tm, _Node, {'EXIT', _Reason}} -> 'EXIT'; + {mnesia_tm, _Node, {dirty_res, _Reply}} -> dirty_res; + {new_store, _Etab} -> new_store; + {new_tid, _Tid, _Etab} -> new_tid; + {ok, _Name, _IgnoreNew, _Node} -> ok; + {restarted, _Tid} -> restarted; + {vote_yes, _Tid, _Self} -> vote_yes; + {vote_yes, _Tid} -> vote_yes; + {acc_pre_commit, _Tid, _Self, _Expect} -> acc_pre_commit; + {schema_commit, _Tid, _Self} -> schema_commit; + {vote_no, _Tid, _Reason} -> vote_no + end; + {'$gen_cast',allow_garb} -> allow_garb; + {'$gen_cast', {release_schema_commit_lock, _Pid}} -> release_schema_commit_lock; + {'$gen_call', _Ref, {mktab, _Name,_Args}} -> mktab; + {'$gen_call', _Ref, wait_for_schema_commit_lock} -> wait_for_schema_commit_lock; + {'$gen_call', _Ref, {set_lock, _Key}} -> set_global_lock; + {'$gen_call', _Ref, {del_lock, _Key}} -> del_global_lock; + {'$gen_call', _Ref, {what_happened, _Decision, _Tid}} -> what_happened; + {async_dump_log, _Reason} -> async_dump_log; + check_overload -> check_overload; + {dumper_done, _Pid, dumped} -> dumper_done; + garb_decisions -> garb_decisions; + timeout -> timeout; + {mnesia_locker, _Node, granted} -> granted; + {mnesia_locker, _Node, {granted, _Lookup}} -> granted; + {'EXIT', _Pid, _Reason} -> 'EXIT'; + {_From, info} -> info; + {_From, start_outer} -> start_outer; + {_From, {add_store, _Tid}} -> add_store; + {_From, {ask_commit, _Prot, _Tid, _Commit, _DiscNs, _RamNs}} -> ask_commit; + {_From, {async_dirty, _Tid, _Commit, _Tab}} -> async_dirty; + {_From, {block_tab, _Tab}} -> block_tab; + {_From, {del_store, _Tid, _Current, _Obsolete, _Prop}} -> del_store; + {_From, {prepare_checkpoint, _Cp}} ->prepare_checkpoint; + {_From, {read, _Tid, _Oid}} -> try_read_lock; + {_From, {read_write, _Tid, _Oid}} -> try_read_write_lock; + {_From, {restart, _Tid, _Store}} -> restart; + {_From, {sync_dirty, _Tid, _Commit, _Tab}} -> sync_dirty; + {_From, {unblock_me, _Tab}} -> unblock_me; + {_From, {unblock_tab, _Tab}} -> unblock_tab; + {_From, {write, _Tid, _Oid}} -> try_write_lock; + {_Tid, committed} -> committed; + {_Tid, do_commit} -> do_commit; + {_Tid, pre_commit} -> pre_commit; + {_Tid, simple_commit} -> simple_commit; + {_Tid, {do_abort, _Reason}} -> do_abort; + {activity_ended, _, _Pid} -> activity_ended; + {ask_commit, _Protocol, _Tid, _Bin, _DiscNs, _RamNs} -> ask_commit; + {delete_transaction, _Tid} -> delete_transaction; + {mnesia_down, _Node} -> mnesia_down; + {release_tid, _Tid} -> release_tid; + {sync_trans_serial, _Tid} -> sync_trans_serial; + {system, _From, _Msg} -> system; + {transaction_done, _Res, _Pid} -> transaction_done; + {_Tid, {do_abort, _Reason}} -> do_abort; + {_Ref, granted} -> granted; + _ -> Label + end. + |