Consolidate data source calls in 1, mockable, module.
[beam_stats.git] / src / beam_stats_process.erl
CommitLineData
5eba068e
SK
1-module(beam_stats_process).
2
3088c08b 3-include("include/beam_stats_process_ancestry.hrl").
5eba068e
SK
4-include("include/beam_stats_process.hrl").
5
6-export_type(
7 [ t/0
8 , status/0
3088c08b 9 , ancestry/0
f2adf421 10 , best_known_origin/0
5eba068e
SK
11 ]).
12
13-export(
14 [ of_pid/1
3088c08b 15 , get_best_known_origin/1
fa175c94 16 , print/1
5eba068e
SK
17 ]).
18
19-type status() ::
20 exiting
21 | garbage_collecting
22 | runnable
23 | running
24 | suspended
25 | waiting
26 .
27
3088c08b
SK
28-type ancestry() ::
29 #beam_stats_process_ancestry{}.
f2adf421
SK
30
31-type best_known_origin() ::
32 {registered_name , atom()}
3088c08b 33 | {ancestry , ancestry()}
f2adf421
SK
34 .
35
5eba068e
SK
36-define(T, #?MODULE).
37
38-type t() ::
39 ?T{}.
40
fa175c94
SK
41%% ============================================================================
42%% Public API
43%% ============================================================================
44
5eba068e
SK
45-spec of_pid(pid()) ->
46 t().
47of_pid(Pid) ->
48 Dict = pid_info_exn(Pid, dictionary),
3088c08b
SK
49 Ancestry =
50 #beam_stats_process_ancestry
51 { raw_initial_call = pid_info_exn(Pid, initial_call)
52 , otp_initial_call = hope_kv_list:get(Dict, '$initial_call')
53 , otp_ancestors = hope_kv_list:get(Dict, '$ancestors')
54 },
5eba068e
SK
55 ?T
56 { pid = Pid
57 , registered_name = pid_info_opt(Pid, registered_name)
3088c08b 58 , ancestry = Ancestry
5eba068e
SK
59 , status = pid_info_exn(Pid, status)
60 , memory = pid_info_exn(Pid, memory)
61 , total_heap_size = pid_info_exn(Pid, total_heap_size)
62 , stack_size = pid_info_exn(Pid, stack_size)
63 , message_queue_len = pid_info_exn(Pid, message_queue_len)
64 }.
65
fa175c94
SK
66-spec print(t()) ->
67 ok.
68print(
69 ?T
70 { pid = Pid
71 , registered_name = RegisteredNameOpt
3088c08b
SK
72 , ancestry = #beam_stats_process_ancestry
73 { raw_initial_call = InitialCallRaw
74 , otp_initial_call = InitialCallOTPOpt
75 , otp_ancestors = AncestorsOpt
76 }
fa175c94
SK
77 , status = Status
78 , memory = Memory
79 , total_heap_size = TotalHeapSize
80 , stack_size = StackSize
81 , message_queue_len = MsgQueueLen
f2adf421 82 }=T
fa175c94 83) ->
3088c08b 84 BestKnownOrigin = get_best_known_origin(T),
fa175c94
SK
85 io:format("--------------------------------------------------~n"),
86 io:format(
87 "Pid : ~p~n"
f2adf421 88 "BestKnownOrigin : ~p~n"
fa175c94
SK
89 "RegisteredNameOpt : ~p~n"
90 "InitialCallRaw : ~p~n"
91 "InitialCallOTPOpt : ~p~n"
92 "AncestorsOpt : ~p~n"
93 "Status : ~p~n"
94 "Memory : ~p~n"
95 "TotalHeapSize : ~p~n"
96 "StackSize : ~p~n"
97 "MsgQueueLen : ~p~n"
98 "~n",
99 [ Pid
f2adf421 100 , BestKnownOrigin
fa175c94
SK
101 , RegisteredNameOpt
102 , InitialCallRaw
103 , InitialCallOTPOpt
104 , AncestorsOpt
105 , Status
106 , Memory
107 , TotalHeapSize
108 , StackSize
109 , MsgQueueLen
110 ]
111 ).
112
113%% ============================================================================
114%% Private helpers
115%% ============================================================================
116
5eba068e
SK
117pid_info_exn(Pid, Key) ->
118 {some, Value} = pid_info_opt(Pid, Key),
119 Value.
120
121pid_info_opt(Pid, Key) ->
aa4143aa 122 case {Key, beam_stats_source:erlang_process_info(Pid, Key)}
5eba068e
SK
123 of {registered_name, []} -> none
124 ; {_ , {Key, Value}} -> {some, Value}
125 end.
f2adf421
SK
126
127%% ============================================================================
128%% Process code origin approximation or naming the anonymous processes.
129%%
130%% At runtime, given a PID, how precicely can we identify the origin of the
131%% code it is running?
132%%
133%% We have these data points:
134%%
135%% - Sometimes | registered name (if so, we're done)
136%% - Sometimes | ancestor PIDs or registered names
137%% - Always | initial_call (can be too generic, such as erlang:apply)
138%% - Always | current_function (can be too far down the stack)
139%% - Always | current_location (can be too far down the stack)
140%% - Potentially | application tree, but maybe expensive to compute, need to check
141%% ============================================================================
142
143-define(TAG(Tag), fun (X) -> {Tag, X} end).
144
3088c08b 145-spec get_best_known_origin(t()) ->
f2adf421 146 best_known_origin().
3088c08b 147get_best_known_origin(?T{registered_name={some, RegisteredName}}) ->
f2adf421 148 {registered_name, RegisteredName};
3088c08b 149get_best_known_origin(?T{registered_name=none, ancestry=Ancestry}) ->
f2adf421 150 {ancestry, Ancestry}.
This page took 0.031487 seconds and 4 git commands to generate.