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. uptimeHow long the device reports it has been running, in seconds (an SNMP sysUpTime scaled from timeticks, or the driver's equivalent). volumeThe output volume a component reports, as a percentage of its range. A settable quantity: the set-volume command opens an intended volume and settles when the component reports it. participant-countThe participants a component reports in its current call; 0 when no call is active. http-response-timeTime for the probe's HTTP request to draw a response (any status); absent when the API never answered. ssh-handshake-timeTime for the SSH key exchange to reach authentication; absent when the daemon never completed it. telnet-response-timeTime for a telnet port to send its first bytes (an option negotiation or a banner) after the connection opened; absent when the port accepted and stayed silent. tls-handshake-timeTime for the TLS handshake to reach the certificate after the connection opened, one observation per probe the component answered; absent when it never answered the handshake. udp-response-timeTime for a udp endpoint's request rung to be answered, from its first send, so a lost datagram's retry shows as time; one observation per probe the component answered, absent when every attempt was lost. snmp-response-timeTime for an snmp endpoint's request rung, a get of a standard OID, to be answered, one observation per probe the agent answered (an authorizationError included); absent when the get went unanswered. tls-certificate-days-leftDays from the probe to the not-after of the certificate a tls probe accepted, to the hundredth, negative once it has expired; one observation per probe, the number a threshold rule reads (an expression cannot read the clock). -
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. A node’s own probe metric (tcp-open,
icmp-rtt-avg and the rest) is a reserved key no contract declares, as on the property side.
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.
Each metric has exactly one writer class, shown on the catalog row as writer_class
(who writes a key): the probe metrics
above are node-probe, written only by the node that probed the endpoint, a calc rule’s output is
calc, and a metric you register is collected, written by a driver’s emits or a push. A write from
anyone the class does not admit is refused naming the key, and a new metric cannot take a native probe
key’s name.
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).