AuroraMeter.LiveDashboard.Sections (Aurora Meter v1.0.0)

View Source

Internal. Not part of the supported API (see API inventory). It may change in any release, including a patch. A host mounts AuroraMeter.LiveDashboard.Page; this is what that page is built from.

The data behind AuroraMeter.LiveDashboard.Page, read without any dashboard dependency at all.

read/1 answers {:ok, data} or {:unavailable, class} for one section. It is a plain module with no Phoenix.LiveDashboard reference, so it is compiled in every build, including one with none of the optional dependencies, and the rules below are testable there.

"Unavailable", never zero

A section that cannot read its source answers {:unavailable, class} and the page renders the word "unavailable" with that class. It never renders 0 and it never renders an empty table, because an operator reads both as "there is nothing wrong" and the case this exists for is the one where something is wrong and nobody can see it. The classes are:

ClassCause
:database_unavailableDBConnection or Postgrex refused the read
:timeoutthe read passed its 2,000 ms budget, or a GenServer.call did
:not_startedthe supervision tree is not running, so the ETS tables or the process are absent
:erroranything else, including a raise inside the reader

Every database read carries timeout: 2_000, takes no lock, opens no transaction and has a bounded result set, so a slow database becomes "unavailable" rather than a hung LiveView.

No tenant-identifying value, anywhere

Every figure here is a node-local aggregate, a checkpoint position or a configuration value. No section returns a tenant key, a feature name, a reference or an event id, which is what lets the core page be shown behind a plain operator marker (AuroraMeter.LiveDashboard.Auth).

That is a live constraint rather than a happy accident: aurora_meter_checkpoints names rows "<operation>:<scope>" and the scope is a tenant key for a per-tenant operation ("lot_migration:org_42"). read(:workers) therefore groups on split_part(name, ':', 1) in SQL and never returns a whole name.

Gauge-derived figures and staleness

Three measurements are sampled on a timer rather than computed on demand: how much is buffered, how old the oldest buffered thing is, and how far behind the cluster is. read/1 reports them from the last emitted sample together with its age, and marks the figure stale when that age is more than three :metrics_intervals. A figure whose sampler has stopped must not look current; the age is shown so an operator can tell a stopped sampler from a slow one.

Every age here is AuroraMeter.Clock.monotonic_ms/0, an in-memory span inside one node. Never a wall clock: a millisecond duration read from a clock that can step backwards is the defect open-findings.md X100 measured.

Summary

Types

Why a section could not be read.

A section's reading, or the class of failure that stopped it.

Functions

The guarantee the metering buffer actually gives, as one line.

Reads one section.

The section names read/1 accepts, in the order the page renders them.

Whether a sample age_ms old is stale, and the threshold that decided it.

Types

class()

@type class() :: :database_unavailable | :timeout | :not_started | :error

Why a section could not be read.

reading()

@type reading() :: {:ok, map()} | {:unavailable, class()}

A section's reading, or the class of failure that stopped it.

Functions

guarantee()

@spec guarantee() :: String.t()

The guarantee the metering buffer actually gives, as one line.

It is on the page because a dashboard that shows a buffer without saying what happens to it invites the reading that the buffer is durable work in progress. It is not: it is a loss window.

Examples

iex> AuroraMeter.LiveDashboard.Sections.guarantee() =~ "can be lost"
true

read(section)

@spec read(atom()) :: reading()

Reads one section.

Returns {:ok, data} or {:unavailable, class}. It never raises and never returns a zero in place of a value it could not read.

Examples

iex> match?({:ok, _} , AuroraMeter.LiveDashboard.Sections.read(:configuration))
true

iex> AuroraMeter.LiveDashboard.Sections.read(:no_such_section)
{:unavailable, :error}

sections()

@spec sections() :: [atom()]

The section names read/1 accepts, in the order the page renders them.

Examples

iex> :metering in AuroraMeter.LiveDashboard.Sections.sections()
true

stale?(age_ms, interval)

@spec stale?(non_neg_integer(), non_neg_integer()) :: boolean()

Whether a sample age_ms old is stale, and the threshold that decided it.

Stale is more than three :metrics_intervals. With metrics_interval: 0 the library drives no timer at all and has no cadence to judge by, so nothing is stale and the age is reported on its own.

Examples

iex> AuroraMeter.LiveDashboard.Sections.stale?(1, 0)
false

iex> AuroraMeter.LiveDashboard.Sections.stale?(40_000, 10_000)
true

iex> AuroraMeter.LiveDashboard.Sections.stale?(20_000, 10_000)
false