X-Git-Url: https://git.xandkar.net/?p=beam_stats.git;a=blobdiff_plain;f=src%2Fbeam_stats_process.erl;h=5dc64d7676262a32a8fd5c3ac75e2719621f3a27;hp=9b2ae8ab3488d158ded9ad04e06c2601e048b0e9;hb=39ff67a62324705869d1ee364e98b17d14e70438;hpb=f2adf421655bc81b4563f2635be271a9f956daf8 diff --git a/src/beam_stats_process.erl b/src/beam_stats_process.erl index 9b2ae8a..5dc64d7 100644 --- a/src/beam_stats_process.erl +++ b/src/beam_stats_process.erl @@ -1,17 +1,18 @@ -module(beam_stats_process). +-include("include/beam_stats_process_ancestry.hrl"). -include("include/beam_stats_process.hrl"). -export_type( [ t/0 , status/0 - , ancestor/0 + , ancestry/0 , best_known_origin/0 ]). -export( - [ of_pid/1 - , best_known_origin/1 + [ of_pid/2 + , get_best_known_origin/1 , print/1 ]). @@ -24,15 +25,12 @@ | waiting . --type ancestor() :: - {otp_ancestors , [pid() | atom()]} - | {otp_initial_call , mfa()} - | {raw_initial_call , mfa()} - . +-type ancestry() :: + #beam_stats_process_ancestry{}. -type best_known_origin() :: {registered_name , atom()} - | {ancestry , [ancestor()]} + | {ancestry , ancestry()} . -define(T, #?MODULE). @@ -44,22 +42,35 @@ %% Public API %% ============================================================================ --spec of_pid(pid()) -> - t(). -of_pid(Pid) -> - Dict = pid_info_exn(Pid, dictionary), - ?T - { pid = Pid - , registered_name = pid_info_opt(Pid, registered_name) - , raw_initial_call = pid_info_exn(Pid, initial_call) - , otp_initial_call = hope_kv_list:get(Dict, '$initial_call') - , otp_ancestors = hope_kv_list:get(Dict, '$ancestors') - , status = pid_info_exn(Pid, status) - , memory = pid_info_exn(Pid, memory) - , total_heap_size = pid_info_exn(Pid, total_heap_size) - , stack_size = pid_info_exn(Pid, stack_size) - , message_queue_len = pid_info_exn(Pid, message_queue_len) - }. +-spec of_pid(pid(), beam_stats_delta:t()) -> + none % when process is dead + | {some, t()} % when process is alive + . +of_pid(Pid, DeltasServer) -> + try + Dict = pid_info_exn(Pid, dictionary), + Ancestry = + #beam_stats_process_ancestry + { raw_initial_call = pid_info_exn(Pid, initial_call) + , otp_initial_call = hope_kv_list:get(Dict, '$initial_call') + , otp_ancestors = hope_kv_list:get(Dict, '$ancestors') + }, + T = + ?T + { pid = Pid + , registered_name = pid_info_opt(Pid, registered_name) + , ancestry = Ancestry + , status = pid_info_exn(Pid, status) + , memory = pid_info_exn(Pid, memory) + , total_heap_size = pid_info_exn(Pid, total_heap_size) + , stack_size = pid_info_exn(Pid, stack_size) + , message_queue_len = pid_info_exn(Pid, message_queue_len) + , reductions = pid_info_reductions(Pid, DeltasServer) + }, + {some, T} + catch throw:{process_dead, _} -> + none + end. -spec print(t()) -> ok. @@ -67,17 +78,20 @@ print( ?T { pid = Pid , registered_name = RegisteredNameOpt - , raw_initial_call = InitialCallRaw - , otp_initial_call = InitialCallOTPOpt - , otp_ancestors = AncestorsOpt + , ancestry = #beam_stats_process_ancestry + { raw_initial_call = InitialCallRaw + , otp_initial_call = InitialCallOTPOpt + , otp_ancestors = AncestorsOpt + } , status = Status , memory = Memory , total_heap_size = TotalHeapSize , stack_size = StackSize , message_queue_len = MsgQueueLen + , reductions = Reductions }=T ) -> - BestKnownOrigin = best_known_origin(T), + BestKnownOrigin = get_best_known_origin(T), io:format("--------------------------------------------------~n"), io:format( "Pid : ~p~n" @@ -91,6 +105,7 @@ print( "TotalHeapSize : ~p~n" "StackSize : ~p~n" "MsgQueueLen : ~p~n" + "Reductions : ~p~n" "~n", [ Pid , BestKnownOrigin @@ -103,6 +118,7 @@ print( , TotalHeapSize , StackSize , MsgQueueLen + , Reductions ] ). @@ -110,14 +126,25 @@ print( %% Private helpers %% ============================================================================ +-spec pid_info_reductions(pid(), beam_stats_delta:t()) -> + non_neg_integer(). +pid_info_reductions(Pid, DeltasServer) -> + case beam_stats_delta:of_process_info_reductions(DeltasServer, Pid) + of {some, Reductions} -> + Reductions + ; none -> + throw({process_dead, Pid}) + end. + pid_info_exn(Pid, Key) -> {some, Value} = pid_info_opt(Pid, Key), Value. pid_info_opt(Pid, Key) -> - case {Key, erlang:process_info(Pid, Key)} + case {Key, beam_stats_source:erlang_process_info(Pid, Key)} of {registered_name, []} -> none ; {_ , {Key, Value}} -> {some, Value} + ; {_ , undefined} -> throw({process_dead, Pid}) end. %% ============================================================================ @@ -138,33 +165,9 @@ pid_info_opt(Pid, Key) -> -define(TAG(Tag), fun (X) -> {Tag, X} end). --spec best_known_origin(t()) -> +-spec get_best_known_origin(t()) -> best_known_origin(). -best_known_origin(?T{registered_name={some, RegisteredName}}) -> +get_best_known_origin(?T{registered_name={some, RegisteredName}}) -> {registered_name, RegisteredName}; -best_known_origin( - ?T - { pid = _Pid - , registered_name = none - , raw_initial_call = InitCallRaw - , otp_initial_call = InitCallOTPOpt1 - , otp_ancestors = AncestorsOpt1 - , status = _Status - , memory = _Memory - , total_heap_size = _TotalHeapSize - , stack_size = _StackSize - , message_queue_len = _MsgQueueLen - } -) -> - ToSingleton = fun (X) -> [X] end, - InitCallOTPOpt2 = hope_option:map(InitCallOTPOpt1, ?TAG(otp_initial_call)), - AncestorsOpt2 = hope_option:map(AncestorsOpt1 , ?TAG(otp_ancestors)), - InitCallOTPOpt3 = hope_option:map(InitCallOTPOpt2, ToSingleton), - AncestorsOpt3 = hope_option:map(AncestorsOpt2 , ToSingleton), - MaybeInitCallOTP = hope_option:get(InitCallOTPOpt3, []), - MaybeAncestors = hope_option:get(AncestorsOpt3 , []), - Ancestry = - [{raw_initial_call, InitCallRaw}] ++ - MaybeInitCallOTP ++ - MaybeAncestors, +get_best_known_origin(?T{registered_name=none, ancestry=Ancestry}) -> {ancestry, Ancestry}.