Erlang如何查看gen_server系列的状态 (高级)
October 29th, 2009
原创文章,转载请注明: 转载自系统技术非业余研究
本文链接地址: Erlang如何查看gen_server系列的状态 (高级)
gen_server在erlang otp编程中的地位是无可撼动的,几乎都是gen_server或者gen_fsm的模型。那么程序运行起来的时候 我们如何查看gen_server的内部状态呢。有2种方法:
1. 自己写个类似于info这样的函数,来获取状态。
2. 利用系统现有的架构。sasl应用带了一个si的东西 全名是status inspector, 这个东西就是设计来帮用户解决这个问题的。
实验开始:
root@nd-desktop:~# cat abc.erl
-module(abc). -behaviour(gen_server). -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([format_status/2]). -export([test/0]). -record(state, {a, b}). -define(SERVER, ?MODULE). start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). test()-> gen_server:call(?SERVER, {test, "param1"}). init([]) -> {ok, #state{a=hello, b=world}}. handle_call({test, _} = Request, _From, State) -> io:format("got msg ~p~n", [Request]), {reply, ok, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. format_status(_Opt, [_PDict, #state{a=A, b = B }]) -> [{data, [{"a===", A}, {"b===", B}]}].
root@nd-desktop:~# erl -boot start_sasl Erlang R13B03 (erts-5.7.4) [source][/source][/source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] =PROGRESS REPORT==== 29-Oct-2009::16:07:24 === supervisor: {local,sasl_safe_sup} started: [{pid,<0.35.0>}, {name,alarm_handler}, {mfa,{alarm_handler,start_link,[]}}, {restart_type,permanent}, {shutdown,2000}, {child_type,worker}] =PROGRESS REPORT==== 29-Oct-2009::16:07:24 === supervisor: {local,sasl_safe_sup} started: [{pid,<0.36.0>}, {name,overload}, {mfa,{overload,start_link,[]}}, {restart_type,permanent}, {shutdown,2000}, {child_type,worker}] =PROGRESS REPORT==== 29-Oct-2009::16:07:24 === supervisor: {local,sasl_sup} started: [{pid,<0.34.0>}, {name,sasl_safe_sup}, {mfa, {supervisor,start_link, [{local,sasl_safe_sup},sasl,safe]}}, {restart_type,permanent}, {shutdown,infinity}, {child_type,supervisor}] =PROGRESS REPORT==== 29-Oct-2009::16:07:24 === supervisor: {local,sasl_sup} started: [{pid,<0.37.0>}, {name,release_handler}, {mfa,{release_handler,start_link,[]}}, {restart_type,permanent}, {shutdown,2000}, {child_type,worker}] =PROGRESS REPORT==== 29-Oct-2009::16:07:24 === application: sasl started_at: nonode@nohost Eshell V5.7.4 (abort with ^G) 1> si:start(). %必须手动启动 =PROGRESS REPORT==== 29-Oct-2009::16:07:31 === supervisor: {local,sasl_sup} started: [{pid,<0.43.0>}, {name,si_server}, {mfa,{si_sasl_supp,start_link,[[]]}}, {restart_type,temporary}, {shutdown,brutal_kill}, {child_type,worker}] {ok,<0.43.0>} 2> si:help(). Status Inspection tool - usage ============================== For all these functions, Opt is an optional argument which can be 'normal' or 'all'; default is 'normal'. If 'all', all information will be printed. A Pid can be: "<A.B.C>", {A, B, C}, B, a registered_name or an abbrev. ANY PROCESS si:pi([Opt,] Pid) - Formatted information about any process that SI recognises. si:pi([Opt,] A,B,C) - Same as si:pi({A, B, C}). si:ppi(Pid) - Pretty formating of process_info. Works for any process. MISC si:abbrevs() - Lists valid abbreviations. si:start_log(Filename) - Logging to file. si:stop_log() si:start() - Starts Status Inspection (the si_server). si:start([{start_log, FileName}]) si:stop() - Shut down SI. ok 3> abc:start_link(). {ok,<0.46.0>} 4> abc:test(). got msg {test,"param1"} ok 5> sys:log(abc,true). %打开gen_server的消息log功能 ok 6> abc:test(). %这个请求消息被记录 got msg {test,"param1"} ok 7> si:pi(abc). %好戏开始 Status for generic server abc =============================================================================== Pid <0.46.0> Status running Parent <0.41.0> Logged events %这个是log到的消息 {10, [{{out,ok,<0.41.0>,{state,hello,world}}, abc, {gen_server,print_event}}, {{in,{'$gen_call',{<0.41.0>,#Ref<0.0.0.85>},{test,"param1"}}}, abc, {gen_server,print_event}}]} %这个是format_status的结果 如果没有format_status那么导出是 {a=hello, b=world} a=== hello b=== world ok 8> si:ppi(abc). Pretty Process Info ------------------- [{registered_name,abc}, {current_function,{gen_server,loop,6}}, {initial_call,{proc_lib,init_p,5}}, {status,waiting}, {message_queue_len,0}, {messages,[]}, {links,[<0.41.0>]}, {dictionary,[{'$ancestors',[<0.41.0>]},{'$initial_call',{abc,init,1}}]}, {trap_exit,false}, {error_handler,error_handler}, {priority,normal}, {group_leader,<0.25.0>}, {total_heap_size,233}, {heap_size,233}, {stack_size,9}, {reductions,117}, {garbage_collection,[{fullsweep_after,65535},{minor_gcs,0}]}, {suspending,[]}] ok 9> sys:get_status(abc). {status,<0.46.0>, {module,gen_server}, [[{'$ancestors',[<0.41.0>]},{'$initial_call',{abc,init,1}}], running,<0.41.0>, [{log,{10, [{{out,ok,<0.41.0>,{state,hello,world}}, abc, {gen_server,print_event}}, {{in,{'$gen_call',{<0.41.0>,#Ref<0.0.0.85>}, {test,"param1"}}}, abc, {gen_server,print_event}}]}}], [abc,{state,hello,world},abc,infinity]]}
结论:
这个是文档未公开的功能。上面演示了如何sys打开log, 如何察看gen_server的状态
Post Footer automatically generated by wp-posturl plugin for wordpress.
erlang:get_status(Name)比较强