Tier 2: named processes, read on the tick.
Never :erlang.processes(). On a node with half a million processes that is
ruinous at 1 Hz, and it is the single easiest way to turn a lightweight
observer into the thing you are debugging. Kepler reads a declared watchlist
and nothing else.
Watches on the same process are read together — one Process.info/2 call per
target per tick, regardless of how many measurements you declared on it.
Measurements
:message_queue_len, :memory, :heap_size, :total_heap_size,
:stack_size, :reductions, and :alive.
:alive is 1 or 0, so "the exporter died" is a condition you can write:
watch :exporter_down do
source process: MyApp.Exporter
measure :alive
fire when: value == 0, sustained: :timer.seconds(10)
endEvery other measurement reports no data when the process is not running, so a watch on a restarting process holds its state rather than firing on the gap.
Summary
Functions
Samples every process watch, grouped by target.
Functions
@spec sample([Kepler.Watch.t()]) :: %{required(atom()) => number() | :no_data}
Samples every process watch, grouped by target.
Returns a map of watch name to value, using :no_data for a target that is
not currently running.