aboutsummaryrefslogtreecommitdiffstats
path: root/lib/et/examples
diff options
context:
space:
mode:
Diffstat (limited to 'lib/et/examples')
-rw-r--r--lib/et/examples/Makefile78
-rw-r--r--lib/et/examples/et_demo.erl351
2 files changed, 429 insertions, 0 deletions
diff --git a/lib/et/examples/Makefile b/lib/et/examples/Makefile
new file mode 100644
index 0000000000..553fe55f3b
--- /dev/null
+++ b/lib/et/examples/Makefile
@@ -0,0 +1,78 @@
+#
+# %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%
+#
+
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(ET_VSN)
+
+# ----------------------------------------------------
+# Release Macros
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/et-$(VSN)
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+
+MODULES = \
+ et_demo
+
+ERL_FILES= $(MODULES:=.erl)
+
+HRL_FILES =
+
+DATA_FILES =
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+# TARGET_FILES =
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += -pa ../../et/ebin
+EBIN = .
+
+# ----------------------------------------------------
+# Make Rules
+# ----------------------------------------------------
+debug opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES) *~
+
+docs:
+
+# ----------------------------------------------------
+# Release Targets
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/examples
+ $(INSTALL_DATA) $(ERL_FILES) $(DATA_FILES) $(HRL_FILES) $(RELSYSDIR)/examples
+
+release_docs_spec:
+
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.
+