Event Tracer (ET) 是Erlang类库里面比较有趣的一个东西,可以使用它进行事件数据收集并进行图形化展示.它可以收集事件数据并进行图形化展示.我觉得在初学阶段用这种方式获得更为直观的印象.官方文档地址:http://www.erlang.org/doc/apps/et/et_intro.html
下面几行代码快速启动了ET,我们看一下:
Eshell V5.9.1 (abort with ^G) 1> {ok, ViewerPid} = et_viewer:start([{title,"Coffee Order"}]), CollectorPid = et_viewer:get_collector_pid(ViewerPid). <0.36.0> 2> et_collector:report_event(CollectorPid,85,from,to,message,extra_stuff). {ok,{table_handle,<0.36.0>,16402,trace_ts, #Fun<et_collector.0.92094374>}} 3>
说明一下:
{ok, ViewerPid} = et_viewer:start([{title,"Coffee Order"}]), %% 启动et_view的UI,并设定窗口的Title显示为Coffe Order
CollectorPid = et_viewer:get_collector_pid(ViewerPid). %% 创建采集器(Collector)进程
et_collector:report_event(CollectorPid,85,from,to,message,extra_stuff).
%% et_collector:report_event(采集器Pid,85,from,to,message,extra_stuff).
上面的85代表信息的详细程度,取值范围是1~100,可以通过这个值做一个简单的消息过滤;
下面利用手头的一个模块做一个demo:
-module(kv_view). -behaviour(gen_server). -export([start/0,start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). % exit(whereis(kv),kill). % % % -define(Server, ?MODULE). start() -> gen_server:start({local,?Server},?MODULE,[],[]). start_link() -> gen_server:start_link({local, ?Server}, ?MODULE, [], []). %%------callbacks init([]) -> process_flag(trap_exit,true), R=ets:new(ets_kv,[named_table, {keypos ,1} ,set]), {ok, Viewer} = et_viewer:start([{title,"K-V View"}, {max_actors,10}]), C = et_viewer:get_collector_pid(Viewer), et_collector:report_event(C,90,shell,k_v_server,init,[R]), {ok ,[{collector,C}]}. handle_call({lookup,Key},From ,[{collector,C}]=S)-> Result =ets:lookup(ets_kv,Key), et_collector:report_event(C,80,From,k_v_server,lookup,[Result]), {reply, Result ,S }; handle_call(mc, _From,{collector,C}=S) -> timer:sleep(8000), et_collector:report_event(C,80,shell,k_v_server,handle_call_but_late,[{sleep,8000}]), {reply, {ok,but_late}, S}; handle_call(_Req, _From,[{collector,C}]=S) -> {reply, ok, S}. handle_cast(stop ,S ) -> {stop,normal,S}; handle_cast({add,K,V} ,[{collector,C}]=S) -> io:format("~p~n",[S]), ets:insert(ets_kv,{K,V}), et_collector:report_event(C,70,shell,k_v_server,handle_call_but_late,[{key,K},{value,V}]), {noreply ,S}; handle_cast(Msg,{collector,C}=S) -> et_collector:report_event(C,60,shell,k_v_server,handle_cast,[{message,Msg}]), {noreply, S}. handle_info(die,S) -> exit(kv_die); % {noreply,S); handle_info(Info, [{collector,C}]=S) -> et_collector:report_event(C,20,shell,k_v_server,handle_info,[{message,Info}]), {noreply, S}. %% 如果进程是在supervisor中,那么如果被supervisor干掉 那么gen_server会调用回调函数terminate(shutdown,State) %% terminate(Reason, _S) -> io:format(" ~p Terminate By Reason: ~p ~n",[ self(),Reason ]), ok. code_change(_Oldvsn, S, _Extra) -> {ok, S}.
调用一下:
Eshell V5.9 (abort with ^G) 1> kv_view:start(). {ok,<0.32.0>} 2> gen_server:cast(kv_view,{add,name,"zen"}). [{collector,<0.37.0>}] ok 3> gen_server:call(kv_view,{lookup,name}). [{name,"zen"}] 4> gen_server:call(kv_view,{lookup,name}). [{name,"zen"}] 5> gen_server:call(kv_view,{lookup,name}). [{name,"zen"}] 6> whereis(kv_view)!hello_world. hello_world 7> whereis(kv_view)!hello_world. hello_world 8> exit(whereis(kv_view)). ** exception exit: <0.32.0> 9>
这样的调用之后,GUI同步绘制下面的图形: