Consolidate data source calls in 1, mockable, module.
[beam_stats.git] / src / beam_stats_process.erl
index 412b4f8..e2751ea 100644 (file)
@@ -1,14 +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
+    , ancestry/0
+    , best_known_origin/0
     ]).
 
 -export(
     [ of_pid/1
+    , get_best_known_origin/1
     , print/1
     ]).
 
     | waiting
     .
 
+-type ancestry() ::
+    #beam_stats_process_ancestry{}.
+
+-type best_known_origin() ::
+      {registered_name , atom()}
+    | {ancestry        , ancestry()}
+    .
+
 -define(T, #?MODULE).
 
 -type t() ::
     t().
 of_pid(Pid) ->
     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
     { 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')
+    , ancestry          = Ancestry
     , status            = pid_info_exn(Pid, status)
     , memory            = pid_info_exn(Pid, memory)
     , total_heap_size   = pid_info_exn(Pid, total_heap_size)
@@ -53,19 +69,23 @@ 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
-    }
+    }=T
 ) ->
+    BestKnownOrigin = get_best_known_origin(T),
     io:format("--------------------------------------------------~n"),
     io:format(
         "Pid               : ~p~n"
+        "BestKnownOrigin   : ~p~n"
         "RegisteredNameOpt : ~p~n"
         "InitialCallRaw    : ~p~n"
         "InitialCallOTPOpt : ~p~n"
@@ -77,6 +97,7 @@ print(
         "MsgQueueLen       : ~p~n"
         "~n",
         [ Pid
+        , BestKnownOrigin
         , RegisteredNameOpt
         , InitialCallRaw
         , InitialCallOTPOpt
@@ -98,7 +119,32 @@ pid_info_exn(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}
     end.
+
+%% ============================================================================
+%% Process code origin approximation or naming the anonymous processes.
+%%
+%% At runtime, given a PID, how precicely can we identify the origin of the
+%% code it is running?
+%%
+%% We have these data points:
+%%
+%% - Sometimes   | registered name (if so, we're done)
+%% - Sometimes   | ancestor PIDs or registered names
+%% - Always      | initial_call (can be too generic, such as erlang:apply)
+%% - Always      | current_function (can be too far down the stack)
+%% - Always      | current_location (can be too far down the stack)
+%% - Potentially | application tree, but maybe expensive to compute, need to check
+%% ============================================================================
+
+-define(TAG(Tag), fun (X) -> {Tag, X} end).
+
+-spec get_best_known_origin(t()) ->
+    best_known_origin().
+get_best_known_origin(?T{registered_name={some, RegisteredName}}) ->
+    {registered_name, RegisteredName};
+get_best_known_origin(?T{registered_name=none, ancestry=Ancestry}) ->
+    {ancestry, Ancestry}.
This page took 0.028146 seconds and 4 git commands to generate.