View Source ZenMonitor (ZenMonitor v2.1.0)
ZenMonitor provides efficient monitoring of remote processes and controlled dissemination of
any resulting :DOWN
messages.
This module provides a convenient client interface which aims to be a drop in replacement for
Process.monitor/1
and Process.demonitor/2
Known differences between ZenMonitor and Process
ZenMonitor.demonitor/2
has the same signature as Process.demonitor/2 but does not respect the:info
option.ZenMonitor aims to be efficient over distribution, one of the main strategies for achieving this is relying mainly on local monitors and then batching up all changes over a time period to be sent as a single message. This design means that additional latency is added to the delivery of down messages in pursuit of the goal. Where
Process.monitor/1
on a remote process will provide a :DOWN message as soon as possible,ZenMonitor.monitor/1
on a remote process will actually have a number of batching periods to go through before the message arrives at the monitoring process, here are all the points that add latency.- When the monitor is enqueued it has to wait until the next sweep happens in the
ZenMonitor.Local.Connector
until it will be delivered to theZenMonitor.Proxy
. - The monitor arrives at the
ZenMonitor.Proxy
, the process crashes and the ERTS:DOWN
message is delivered. This will be translated into a death_certificate and sent to aZenMonitor.Proxy.Batcher
for delivery. It will have to wait until the next sweep happens for it to be sent back to theZenMonitor.Local.Connector
for fan-out. - The dead summary including the death_certificate arrives at the
ZenMonitor.Local.Connector
and a down_dispatch is created for it and enqueued with theZenMonitor.Local
. - The down_dispatch waits in a queue until the
ZenMonitor.Local.Dispatcher
generates more demand. - Once demand is generated,
ZenMonitor.Local
will hand off the down_dispatch for actual delivery byZenMonitor.Local.Dispatcher
.
- Steps 1 and 3 employ a strategy of batch sizing to prevent the message from growing too
large. The batch size is controlled by application configuration and is alterable at boot
and runtime. This means though that Steps 1 and 3 can be delayed by N intervals
where
N = ceil(items_ahead_of_event / chunk_size)
- Step 4 employs a similar batching strategy, a down_dispatch will wait in queue for up to N
intervals where
N = ceil(items_ahead_of_dispatch / chunk_size)
- When the monitor is enqueued it has to wait until the next sweep happens in the
ZenMonitor
decorates the reason of the:DOWN
message. If a remote process goes down because oforiginal_reason
, this will get decorated as{:zen_monitor, original_reason}
when delivered by ZenMonitor. This allows the receiver to differentiate:DOWN
messages originating fromZenMonitor.monitor/1
and those originating fromProcess.monitor/1
. This is necessary when operating in mixed mode. It is the responsibility of the receiver to unwrap this reason if it requires theoriginal_reason
for some additional handling of the:DOWN
message.
Link to this section Summary
Types
ZenMonitor.destination
are all the types that can be monitored.
Functions
Delegate to ZenMonitor.Local.Connector.connect/1
Find the node for a destination.
Get the module to use for gen calls from the Application Environment
Put the module to use for gen calls into the Application Environment
Delegate to ZenMonitor.Local.monitor/1
Get the current monotonic time in milliseconds
Link to this section Types
Specs
ZenMonitor.destination
are all the types that can be monitored.
pid()
either local or remote{name, node}
represents a named process on the given nodename :: atom()
is a named process on the local node
Link to this section Functions
Delegate to ZenMonitor.Local.compatibility/1
Delegate to ZenMonitor.Local.compatibility_for_node/1
Delegate to ZenMonitor.Local.Connector.connect/1
Delegate to ZenMonitor.Local.demonitor/2
Specs
find_node(target :: destination()) :: node()
Find the node for a destination.
Specs
gen_module() :: atom()
Get the module to use for gen calls from the Application Environment
This module only needs to support GenServer.call/3
and GenServer.cast/2
functionality, see
ZenMonitor's @gen_module
for the default value
This can be controlled at boot and runtime with the {:zen_monitor, :gen_module}
setting, see
ZenMonitor.gen_module/1
for runtime convenience functionality.
Specs
gen_module(value :: atom()) :: :ok
Put the module to use for gen calls into the Application Environment
This is a simple convenience function for overwriting the {:zen_monitor, :gen_module}
setting
at runtime.
Delegate to ZenMonitor.Local.monitor/1
Specs
now() :: integer()
Get the current monotonic time in milliseconds
This is a helper because System.monotonic_time(:milliseconds)
is long and error-prone to
type in multiple call sites.
See System.monotonic_time/1
for more information.