, reductions :: non_neg_integer()
, run_queue :: non_neg_integer()
, ets :: beam_stats_ets:t()
+ , processes :: beam_stats_processes:t()
%, statistics :: [{atom() , term()}]
%, system :: [{atom() , term()}]
- %, process :: [{atom() , term()}]
%, port :: [{atom() , term()}]
%, dets :: [{atom() , term()}]
}).
--- /dev/null
+-record(beam_stats_process,
+ { pid :: pid()
+ , registered_name :: hope_option:t(atom())
+ , raw_initial_call :: mfa()
+ , otp_initial_call :: hope_option:t(mfa())
+ , otp_ancestors :: [{name, atom()} | {call, mfa()}]
+ , status :: beam_stats_process:status()
+ , memory :: non_neg_integer()
+ , total_heap_size :: non_neg_integer()
+ , stack_size :: non_neg_integer()
+ , message_queue_len :: non_neg_integer()
+ }).
--- /dev/null
+-record(beam_stats_processes,
+ { individual_stats = [] :: [beam_stats_process:t()]
+ , count_all = 0 :: non_neg_integer()
+ , count_exiting = 0 :: non_neg_integer()
+ , count_garbage_collecting = 0 :: non_neg_integer()
+ , count_registered = 0 :: non_neg_integer()
+ , count_runnable = 0 :: non_neg_integer()
+ , count_running = 0 :: non_neg_integer()
+ , count_suspended = 0 :: non_neg_integer()
+ , count_waiting = 0 :: non_neg_integer()
+ }).
--- /dev/null
+-module(beam_stats_process).
+
+-include("include/beam_stats_process.hrl").
+
+-export_type(
+ [ t/0
+ , status/0
+ ]).
+
+-export(
+ [ of_pid/1
+ ]).
+
+-type status() ::
+ exiting
+ | garbage_collecting
+ | runnable
+ | running
+ | suspended
+ | waiting
+ .
+
+-define(T, #?MODULE).
+
+-type t() ::
+ ?T{}.
+
+-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)
+ }.
+
+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)}
+ of {registered_name, []} -> none
+ ; {_ , {Key, Value}} -> {some, Value}
+ end.
--- /dev/null
+-module(beam_stats_processes).
+
+-include("include/beam_stats_process.hrl").
+-include("include/beam_stats_processes.hrl").
+
+-export_type(
+ [ t/0
+ ]).
+
+-export(
+ [ collect/0
+ ]).
+
+-define(T, #?MODULE).
+
+-type t() ::
+ ?T{}.
+
+-spec collect() ->
+ t().
+collect() ->
+ Ps = [beam_stats_process:of_pid(P) || P <- erlang:processes()],
+ ?T
+ { individual_stats
+ = Ps
+ , count_all
+ = length(Ps)
+ , count_exiting
+ = length([P || P <- Ps, P#beam_stats_process.status =:= exiting])
+ , count_garbage_collecting
+ = length([P || P <- Ps, P#beam_stats_process.status =:= garbage_collecting])
+ , count_registered
+ = length(registered())
+ , count_runnable
+ = length([P || P <- Ps, P#beam_stats_process.status =:= runnable])
+ , count_running
+ = length([P || P <- Ps, P#beam_stats_process.status =:= running])
+ , count_suspended
+ = length([P || P <- Ps, P#beam_stats_process.status =:= suspended])
+ , count_waiting
+ = length([P || P <- Ps, P#beam_stats_process.status =:= waiting])
+ }.
-module(beam_stats_state).
-include("include/beam_stats.hrl").
+-include("include/beam_stats_process.hrl").
+-include("include/beam_stats_processes.hrl").
-export_type(
[ t/0
-record(snapshots,
{ memory :: [{atom(), non_neg_integer()}]
+ , processes :: beam_stats_processes:t()
, run_queue :: non_neg_integer()
, ets :: beam_stats_ets:t()
}).
, snapshots =
#snapshots
{ memory = Memory
+ , processes = Processes
, run_queue = RunQueue
, ets = ETS
}
, reductions = Reductions
, run_queue = RunQueue
, ets = ETS
+ , processes = Processes
}.
snapshots_new() ->
#snapshots
{ memory = erlang:memory()
+ , processes = beam_stats_processes:collect()
, run_queue = erlang:statistics(run_queue)
, ets = beam_stats_ets:collect()
}.