PhiAccrual (phi_accrual v1.0.0)

View Source

φ-accrual failure detector — public API.

The detector emits a continuous suspicion value φ per monitored node. φ grows monotonically with time since the last heartbeat and is calibrated against observed inter-arrival statistics (EWMA mean and variance). See PhiAccrual.Core for the math and README.md for the positioning (observability-grade, not decision-grade in v1).

Typical usage (bring-your-own-signal)

# Track a node with default estimator settings.
PhiAccrual.track(:node_a@host)

# Call observe/2 from wherever you already receive cross-node
# traffic — GenServer replies, :pg broadcasts, your own pings.
PhiAccrual.observe(:node_a@host)

# Query φ at any time.
PhiAccrual.phi(:node_a@host)
#=> {:ok, 1.82, :steady}

observe/1 auto-tracks unknown nodes with default settings — call track/2 first if you want custom per-node estimator options.

Overload behaviour

observe/2 is bounded: if the target estimator's mailbox exceeds :shed_threshold (default 10_000) the sample is dropped and a [:phi_accrual, :overload, :shed] telemetry event is emitted. For failure detection you don't need every heartbeat, you need enough heartbeats — if you're shedding, your heartbeat rate is too high for your EWMA α settings. Tune α before raising the threshold.

Summary

Functions

Return the current PhiAccrual.Core estimator state for node, or {:error, :not_tracked} if the node is not tracked.

Record a heartbeat arrival for node at the current monotonic time. Auto-tracks the node with default options if not already tracked.

Record a heartbeat arrival for node at monotonic-ms ts.

Current φ for node. See PhiAccrual.Core.phi_result/0.

Start tracking node with optional estimator configuration.

List all currently-tracked nodes.

Stop tracking node. No-op if the node is not tracked.

Types

phi_result()

@type phi_result() :: PhiAccrual.Core.phi_result()

Functions

inspect_state(node)

@spec inspect_state(node()) :: PhiAccrual.Core.t() | {:error, :not_tracked}

Return the current PhiAccrual.Core estimator state for node, or {:error, :not_tracked} if the node is not tracked.

Intended for IEx introspection and debugging — inspect mean, variance, samples_seen, last_interval_ms, and last_arrival_ts to see what the estimator currently believes about a node. Not for hot-path use.

observe(node)

@spec observe(node()) :: :ok

Record a heartbeat arrival for node at the current monotonic time. Auto-tracks the node with default options if not already tracked.

observe(node, ts)

@spec observe(node(), integer()) :: :ok

Record a heartbeat arrival for node at monotonic-ms ts.

ts must come from the same local monotonic clock as Clock.now/0. Cross-node timestamps are meaningless for the detector and must never enter interval calculations.

phi(node)

@spec phi(node()) :: phi_result() | {:error, :not_tracked}

Current φ for node. See PhiAccrual.Core.phi_result/0.

track(node, core_opts \\ [])

@spec track(
  node(),
  keyword()
) :: {:ok, pid()} | {:error, term()}

Start tracking node with optional estimator configuration.

core_opts are forwarded to PhiAccrual.Core.new/1.

tracked_nodes()

@spec tracked_nodes() :: [node()]

List all currently-tracked nodes.

untrack(node)

@spec untrack(node()) :: :ok

Stop tracking node. No-op if the node is not tracked.