Metrics
Catalog, under Telemetry: Metrics (with metric_type:read, covered by every viewer’s *:read floor) is the
numeric lane of the fleet’s signal catalog: the directory of the quantities the fleet
measures. A metric is a quantity: a numeric reading that aggregates, so an average, a
p95, a rate over time all mean something, and beside its name and data type it carries the numeric
facts, a display unit and a precision, that the property lane never holds. A
property is the other lane: a value, including a number used as a
name (a serial number identifies a unit, it measures nothing).
A metric is used in three moves, and this page walks all three: the catalog names it, a
classifier declares it (with a default, and whether it is required), and telemetry fills
it, one series row per reading, with the current value read from the series. The name is the
metric’s canonical identifier, a single lowercase kebab segment, and the same metric is the same
comparable series wherever it appears: registering icmp-rtt-avg once means every device’s
round-trip time lands under one name, in one unit, across vendors.
The catalog is fleet-wide reference data, not a scoped resource, so every metric is visible to every reader; the write gates decide who may change it.
-
The directory lists every metric sorted by name, each showing its name (the canonical identifier, with its label on the line above it), type (
intorfloat), unit, and origin (official or custom). name filters by the name or its label; type, unit, and official narrow the list. -
New metric (with
metric_type:create, granted to operators) opens a create drawer: give it a name (a single lowercase kebab segment, for exampleicmp-rtt-avgorcpu-load), choose its data type (intorfloat; a metric is always a number, a categorical signal is a property), and optionally add a label, a description, a unit (ms,dB,percent), and a precision (the decimal places a rendered value keeps). An invalid name (an uppercase letter, an underscore, a leading hyphen, a dot) is refused with a message. -
The unit is canonical: stored values are always in it, so every threshold and calculation compares like with like. A genuinely different measurement is a different metric; the unit names the scale, it never rides along per sample.
-
Pick a row to open its detail blade. The footer Edit pencil (with
metric_type:update) edits the label, description, unit, and precision; the name and data type are fixed at creation, since changing a series’ value type under the rows that already use it is unsafe and a name is what every driver and contract maps onto. Delete (withmetric_type:delete) removes a custom metric, behind a confirm. A verb you lack greys just that button, its hover reason naming the permission (Requires metric_type:update,Requires metric_type:delete); the pair never disappears. -
An official metric is always read-only: the blade keeps the Edit and Delete pair in place, greyed, with the reason on hover: “Official: ships with Omniglass and updates with it.” The shared vocabulary is the same from install to install, the same deliberate exception to the operator-owned rule the Properties catalog makes, and for the same reason: a metric name is the vocabulary a driver maps onto, so a release has to be able to correct it (the seed model).
The baseline ships this catalog, rendered from the seed itself (
make gen) so the list cannot drift from the binary:Name Description icmp-reachableICMP inline probe result (1 = at least one echo returned, 0 = none). icmp-rtt-avgAverage round-trip time over the task's echoes; absent when unreachable. tcp-openTCP-connect probe result (1 = the port accepted a connection, 0 = refused/timeout). tcp-connect-timeTime to establish the TCP connection; absent when the port is closed. room-temperatureAmbient temperature reported for the space, in degrees Celsius. occupancy-countPeople detected in the space by the room's occupancy source. -
A duplicate name is refused (409), and an attempt to change an official metric is refused too. The refusal reaches across lanes: the metric, property, and event catalogs share one namespace, so a name one of them holds cannot be registered in another, which is what keeps per-lane routing unambiguous.
The catalog is also the collection vocabulary: a pushed sample lands in the metric series only if its name is registered here; an unregistered name is rejected and reported in the push response, not silently dropped and not invented.
Declare a metric on a classifier
Section titled “Declare a metric on a classifier”The catalog says a metric exists; a classifier says which metrics its instances carry.
The contract shape is the same as the property contract,
held in the metric siblings of the property contract tables (product_metric,
standard_metric, location_type_metric): a product declares for its
components, a standard for its systems, and a
location type for the locations of that type. Each line names a catalog
metric, optionally gives it a default, and optionally marks it required: a product ships a
default sample rate, a standard requires a seat count.
Type, unit, and precision are not repeated in the contract; they stay on the catalog entry, so
a metric means one thing everywhere. The contract lines that predate the two-lane split moved into
these tables when the catalog divided, and the classifier blades edit both lanes: a Declared
metrics panel sits beside the declared-properties one on the product, standard, and location
type blades, over the contract’s own routes (/products/{id}/metrics and its standard and
location-type siblings, mirrored in the generated CLI). An instance resolves a declared
metric to its series’ latest observed or calculated sample, falling back to the contract default
until one arrives; the per-owner reads (/components/{name}/metrics and its system and location
siblings) answer that resolution beside any off-contract series the owner holds.
Where a metric’s values come from
Section titled “Where a metric’s values come from”A metric’s values are telemetry, not something typed on an instance’s detail:
- An observed value arrives through collection: a task samples
the device and pushes the reading. The shipped probes are the seeded set above: the TCP-connect
probe writes
tcp-openandtcp-connect-time, the ICMP probe writesicmp-reachableandicmp-rtt-avg. - A calculated value is produced by a rule from other telemetry, and the row names the rule that produced it, so a derived number is never mistaken for a reading.
- A command that targets a metric (set a volume) records the value it intends, landing beside the observed series so intent and reality can be compared.
The current value is the latest series row: “what is this metric now?” is answered by reading
the newest row for that metric on that owner, not from a separately maintained copy
(the sample lanes). A declared metric value is not writable
today: the metric lane refuses declared provenance until a writer exists, so a number an
operator asserts by hand has nowhere to land yet.
From the CLI, the catalog is omniglass metric-type list|get|create|update|delete (see the
CLI reference).