Authors: Fred Hebert (mononcqc@ferd.ca) [web site: http://ferd.ca/].
Recon, as a module, provides access to the high-level functionality contained in the Recon application.
It has functions in five main categories:
info/1
and info/3
are wrappers to provide more details than
erlang:process_info/1
, while providing it in a production-safe
manner. They have equivalents to erlang:process_info/2
in
the functions info/2
and info/4
, respectively.proc_count/2
and proc_window/3
are to be used
when you require information about processes in a larger sense:
biggest consumers of given process information (say memory or
reductions), either absolutely or over a sliding time window,
respectively.bin_leak/1
is a function that can be used to try and
see if your Erlang node is leaking refc binaries. See the function
itself for more details.node_stats_print/2
, which displays them,
node_stats_list/2
, which returns them in a list, and
node_stats/4
, which provides a fold-like interface
for stats gathering. For CPU usage specifically, see
scheduler_usage/1
.get_state/1
, which works as a wrapper around
get_state/2
, which works as a wrapper around
sys:get_state/1
in R16B01, and provides the required
functionality for older versions of Erlang.recon
for the sole purpose
of interacting with source and compiled code.
remote_load/1
and remote_load/2
will allow
to take a local module, and load it remotely (in a diskless
manner) on another Erlang node you're connected to.source/1
allows to print the source of a loaded module,
in case it's not available in the currently running node.tcp/0
, udp/0
,
sctp/0
, files/0
, and port_types/0
will
list all the Erlang ports of a given type. The latter function
prints counts of all individual types.port_info/1
and port_info/2
are wrappers to provide
more similar or more details than erlang:port_info/1-2
, and, for
inet ports, statistics and options for each socket.inet_count/2
and inet_window/3
provide the absolute or sliding window functionality of
proc_count/2
and proc_count/3
to inet ports
and connections currently on the node.rpc
module)
make it somewhat painful to call shell-defined funs over node
boundaries. The functions rpc/1
, rpc/2
, and
rpc/3
will do it with a simpler interface.named_rpc/1
, named_rpc/2
, and named_rpc/3
will wrap the results in a tuple that tells you which node it's
coming from, making it easier to identify bad nodes.inet_attrs() = {port(), Attr::term(), [{atom(), term()}]}
info_key() = info_meta_key() | info_signals_key() | info_location_key() | info_memory_key() | info_work_key()
info_location_key() = initial_call | current_stacktrace
info_memory_key() = memory | message_queue_len | heap_size | total_heap_size | garbage_collection
info_meta_key() = registered_name | dictionary | group_leader | status
info_signals_key() = links | monitors | monitored_by | trap_exit
info_type() = meta | signals | location | memory_used | work
info_work_key() = reductions
pid_term() = pid() | atom() | string() | {global, term()} | {via, module(), term()} | {non_neg_integer(), non_neg_integer(), non_neg_integer()}
port_info_io_key() = input | output
port_info_key() = port_info_meta_key() | port_info_signals_key() | port_info_io_key() | port_info_memory_key() | port_info_specific_key()
port_info_memory_key() = memory | queue_size
port_info_meta_key() = registered_name | id | name | os_pid
port_info_signals_key() = connected | links | monitors
port_info_specific_key() = atom()
port_info_type() = meta | signals | io | memory_used | specific
port_term() = port() | string() | atom() | pos_integer()
proc_attrs() = {pid(), Attr::term(), [Name::atom() | {current_function, mfa()} | {initial_call, mfa()}, ...]}
bin_leak/1 | Refc binaries can be leaking when barely-busy processes route them around and do little else, or when extremely busy processes reach a stable amount of memory allocated and do the vast majority of their work with refc binaries. |
files/0 | (Deprecated.) returns a list of all file handles open on the node. |
get_state/1 | Shorthand call to recon:get_state(PidTerm, 5000) |
get_state/2 | Fetch the internal state of an OTP process. |
inet_count/2 | Fetches a given attribute from all inet ports (TCP, UDP, SCTP)
and returns the biggest Num consumers. |
inet_window/3 | Fetches a given attribute from all inet ports (TCP, UDP, SCTP) and returns the biggest entries, over a sliding time window. |
info/1 | Allows to be similar to erlang:process_info/1 , but excludes fields
such as the mailbox, which have a tendency to grow and be unsafe when called
in production systems. |
info/2 | Allows to be similar to erlang:process_info/2 , but allows to
sort fields by safe categories and pre-selections, avoiding items such
as the mailbox, which may have a tendency to grow and be unsafe when
called in production systems. |
info/3 | Equivalent to info(<A.B.C>) where A , B , and C are integers part
of a pid. |
info/4 | Equivalent to info(<A.B.C>, Key) where A , B , and C are integers part
of a pid. |
named_rpc/1 | Shorthand for named_rpc([node()|nodes()], Fun) . |
named_rpc/2 | Shorthand for named_rpc(Nodes, Fun, infinity) . |
named_rpc/3 | Runs an arbitrary fun (of arity 0) over one or more nodes, and returns the name of the node that computed a given result along with it, in a tuple. |
node_stats/4 | Gathers statistics N time, waiting Interval milliseconds between
each run, and accumulates results using a folding function FoldFun . |
node_stats_list/2 | Shorthand for node_stats(N, Interval, fun(X,Acc) -> [X|Acc] end, [])
with the results reversed to be in the right temporal order. |
node_stats_print/2 | Shorthand for node_stats(N, Interval, fun(X,_) -> io:format("~p~n",[X]) end, nostate) . |
port_info/1 | Allows to be similar to erlang:port_info/1 , but allows
more flexible port usage: usual ports, ports that were registered
locally (an atom), ports represented as strings ("#Port<0.2013>" ),
or through an index lookup (2013 , for the same result as
"#Port<0.2013>" ). |
port_info/2 | Allows to be similar to erlang:port_info/2 , but allows
more flexible port usage: usual ports, ports that were registered
locally (an atom), ports represented as strings ("#Port<0.2013>" ),
or through an index lookup (2013 , for the same result as
"#Port<0.2013>" ). |
port_types/0 | Shows a list of all different ports on the node with their respective types. |
proc_count/2 | Fetches a given attribute from all processes (except the
caller) and returns the biggest Num consumers. |
proc_window/3 | Fetches a given attribute from all processes (except the caller) and returns the biggest entries, over a sliding time window. |
remote_load/1 | Equivalent to remote_load(nodes(), Mod). |
remote_load/2 | Loads one or more modules remotely, in a diskless manner. |
rpc/1 | Shorthand for rpc([node()|nodes()], Fun) . |
rpc/2 | Shorthand for rpc(Nodes, Fun, infinity) . |
rpc/3 | Runs an arbitrary fun (of arity 0) over one or more nodes. |
scheduler_usage/1 | Because Erlang CPU usage as reported from top isn't the most
reliable value (due to schedulers doing idle spinning to avoid going
to sleep and impacting latency), a metric exists that is based on
scheduler wall time. |
sctp/0 | returns a list of all SCTP ports (the data type) open on the node. |
source/1 | Obtain the source code of a module compiled with debug_info . |
tcp/0 | returns a list of all TCP ports (the data type) open on the node. |
udp/0 | returns a list of all UDP ports (the data type) open on the node. |
bin_leak(N::pos_integer()) -> [proc_attrs()]
Refc binaries can be leaking when barely-busy processes route them
around and do little else, or when extremely busy processes reach a stable
amount of memory allocated and do the vast majority of their work with refc
binaries. When this happens, it may take a very long while before references
get deallocated and refc binaries get to be garbage collected, leading to
Out Of Memory crashes.
This function fetches the number of refc binary references in each process
of the node, garbage collects them, and compares the resulting number of
references in each of them. The function then returns the N
processes
that freed the biggest amount of binaries, potentially highlighting leaks.
files() -> [port()]
This function is deprecated: Starting with OTP-21, files are implemented as NIFs and can no longer be listed. This function returns an empty list in such a case.
returns a list of all file handles open on the node.
get_state(PidTerm::pid_term()) -> term()
Shorthand call to recon:get_state(PidTerm, 5000)
get_state(PidTerm::pid_term(), Ms::non_neg_integer() | infinity) -> term()
Fetch the internal state of an OTP process.
Calls sys:get_state/2
directly in R16B01+, and fetches
it dynamically on older versions of OTP.
inet_count(AttributeName, Num) -> [inet_attrs()]
Fetches a given attribute from all inet ports (TCP, UDP, SCTP)
and returns the biggest Num
consumers.
send_oct
, recv_oct
, oct
, respectively), or the number
of packets sent, received, or both (send_cnt
, recv_cnt
, cnt
,
respectively). Individual absolute values for each metric will be returned
in the 3rd position of the resulting tuple.
inet_window(AttributeName, Num, Milliseconds) -> [inet_attrs()]
Fetches a given attribute from all inet ports (TCP, UDP, SCTP) and returns the biggest entries, over a sliding time window.
Warning: this function depends on data gathered at two snapshots, and then building a dictionary with entries to differentiate them. This can take a heavy toll on memory when you have many dozens of thousands of ports open.
The values to be used can be the number of octets (bytes) sent, received, or both (send_oct
, recv_oct
, oct
, respectively), or the number
of packets sent, received, or both (send_cnt
, recv_cnt
, cnt
,
respectively). Individual absolute values for each metric will be returned
in the 3rd position of the resulting tuple.
info(PidTerm::pid_term()) -> [{info_type(), [{info_key(), Value}]}, ...]
Allows to be similar to erlang:process_info/1
, but excludes fields
such as the mailbox, which have a tendency to grow and be unsafe when called
in production systems. Also includes a few more fields than what is usually
given (monitors
, monitored_by
, etc.), and separates the fields in a more
readable format based on the type of information contained.
{global, Name}
), or through
another registry supported in the {via, Module, Name}
syntax (must have a
Module:whereis_name/1
function). Pids can also be passed in as a string
("<0.39.0>"
) or a triple ({0,39,0}
) and will be converted to be used.
info(PidTerm::pid_term(), Keys::info_type()) -> {info_type(), [{info_key(), term()}]}
Allows to be similar to erlang:process_info/2
, but allows to
sort fields by safe categories and pre-selections, avoiding items such
as the mailbox, which may have a tendency to grow and be unsafe when
called in production systems.
Moreover, it will fetch and read information on local processes that were
registered locally (an atom), globally ({global, Name}
), or through
another registry supported in the {via, Module, Name}
syntax (must have a
Module:whereis_name/1
function). Pids can also be passed in as a string
("<0.39.0>"
) or a triple ({0,39,0}
) and will be converted to be used.
Although the type signature doesn't show it in generated documentation,
a list of arguments or individual arguments accepted by
erlang:process_info/2
and return them as that function would.
binary_memory
is also available to return the
amount of memory used by refc binaries for a process.
info(N, N, N) -> [{info_type(), [{info_key(), term()}]}, ...]
Equivalent to info(<A.B.C>)
where A
, B
, and C
are integers part
of a pid
info(N, N, N, Key) -> term()
Equivalent to info(<A.B.C>, Key)
where A
, B
, and C
are integers part
of a pid
named_rpc(Fun::fun(() -> term())) -> {[Success::term()], [Fail::term()]}
Shorthand for named_rpc([node()|nodes()], Fun)
.
named_rpc(Nodes::node() | [node(), ...], Fun::fun(() -> term())) -> {[Success::term()], [Fail::term()]}
Shorthand for named_rpc(Nodes, Fun, infinity)
.
named_rpc(Nodes::node() | [node(), ...], Fun::fun(() -> term()), Timeout::timeout()) -> {[Success::term()], [Fail::term()]}
Runs an arbitrary fun (of arity 0) over one or more nodes, and returns the name of the node that computed a given result along with it, in a tuple.
node_stats(N, Interval, FoldFun, Acc) -> Acc
Gathers statistics N
time, waiting Interval
milliseconds between
each run, and accumulates results using a folding function FoldFun
.
The function will gather statistics in two forms: Absolutes and Increments.
Absolutes are values that keep changing with time, and are useful to know about as a datapoint: process count, size of the run queue, error_logger queue length in versions before OTP-21 or those thar run it explicitely, and the memory of the node (total, processes, atoms, binaries, and ets tables).
Increments are values that are mostly useful when compared to a previous one to have an idea what they're doing, because otherwise they'd never stop increasing: bytes in and out of the node, number of garbage colelctor runs, words of memory that were garbage collected, and the global reductions count for the node.node_stats_list(Repeat, Interval) -> [Stats]
Shorthand for node_stats(N, Interval, fun(X,Acc) -> [X|Acc] end, [])
with the results reversed to be in the right temporal order.
node_stats_print(Repeat, Interval) -> term()
Shorthand for node_stats(N, Interval, fun(X,_) -> io:format("~p~n",[X]) end, nostate)
.
port_info(PortTerm::port_term()) -> [{port_info_type(), [{port_info_key(), term()}]}, ...]
Allows to be similar to erlang:port_info/1
, but allows
more flexible port usage: usual ports, ports that were registered
locally (an atom), ports represented as strings ("#Port<0.2013>"
),
or through an index lookup (2013
, for the same result as
"#Port<0.2013>"
).
Moreover, the function will try to fetch implementation-specific details based on the port type (only inet ports have this feature so far). For example, TCP ports will include information about the remote peer, transfer statistics, and socket options being used.
The information-specific and the basic port info are sorted and categorized in broader categories (port_info_type()
).
port_info(PortTerm::port_term(), Keys::port_info_type()) -> {port_info_type(), [{port_info_key(), term()}]}
Allows to be similar to erlang:port_info/2
, but allows
more flexible port usage: usual ports, ports that were registered
locally (an atom), ports represented as strings ("#Port<0.2013>"
),
or through an index lookup (2013
, for the same result as
"#Port<0.2013>"
).
port_info_type()
, and although the type signature
doesn't show it in the generated documentation, individual items
accepted by erlang:port_info/2
are accepted, and lists of them too.
port_types() -> [{Type::string(), Count::pos_integer()}]
Shows a list of all different ports on the node with their respective types.
proc_count(AttributeName, Num) -> [proc_attrs()]
Fetches a given attribute from all processes (except the
caller) and returns the biggest Num
consumers.
proc_window(AttributeName, Num, Milliseconds) -> [proc_attrs()]
Fetches a given attribute from all processes (except the caller) and returns the biggest entries, over a sliding time window.
This function is particularly useful when processes on the node are mostly short-lived, usually too short to inspect through other tools, in order to figure out what kind of processes are eating through a lot resources on a given node.
It is important to see this function as a snapshot over a sliding window. A program's timeline during sampling might look like this:
--w---- [Sample1] ---x-------------y----- [Sample2] ---z--->
Some processes will live between w
and die at x
, some between y
and
z
, and some between x
and y
. These samples will not be too significant
as they're incomplete. If the majority of your processes run between a time
interval x
...y
(in absolute terms), you should make sure that your
sampling time is smaller than this so that for many processes, their
lifetime spans the equivalent of w
and z
. Not doing this can skew the
results: long-lived processes, that have 10 times the time to accumulate
data (say reductions) will look like bottlenecks when they're not one.
remote_load(Mod::module()) -> term()
Equivalent to remote_load(nodes(), Mod).
remote_load(Nodes, Mod::module()) -> term()
Loads one or more modules remotely, in a diskless manner. Allows to share code loaded locally with a remote node that doesn't have it
rpc(Fun::fun(() -> term())) -> {[Success::term()], [Fail::term()]}
Shorthand for rpc([node()|nodes()], Fun)
.
rpc(Nodes::node() | [node(), ...], Fun::fun(() -> term())) -> {[Success::term()], [Fail::term()]}
Shorthand for rpc(Nodes, Fun, infinity)
.
rpc(Nodes::node() | [node(), ...], Fun::fun(() -> term()), Timeout::timeout()) -> {[Success::term()], [Fail::term()]}
Runs an arbitrary fun (of arity 0) over one or more nodes.
scheduler_usage(Millisecs) -> undefined | [{SchedulerId, Usage}]
Because Erlang CPU usage as reported from top
isn't the most
reliable value (due to schedulers doing idle spinning to avoid going
to sleep and impacting latency), a metric exists that is based on
scheduler wall time.
For any time interval, Scheduler wall time can be used as a measure of how 'busy' a scheduler is. A scheduler is busy when:
sctp() -> [port()]
returns a list of all SCTP ports (the data type) open on the node.
source(Module::module()) -> iolist()
Obtain the source code of a module compiled with debug_info
.
The returned list sadly does not allow to format the types and typed
records the way they look in the original module, but instead goes to
an intermediary form used in the AST. They will still be placed
in the right module attributes, however.
tcp() -> [port()]
returns a list of all TCP ports (the data type) open on the node.
udp() -> [port()]
returns a list of all UDP ports (the data type) open on the node.
Generated by EDoc