Events
PartialAn event is our semantic assertion that something happened, in our vocabulary: a discrete, point-in-time occurrence the action layer reacts to, owned through the same exclusive-arc as a sample. It is not a sample (the has-a-value-now razor): samples are what rules read, events are what event rules produce. The rules live on calculations; alarms and the responding actions on alarms and actions.
The event_type registry
Section titled “The event_type registry”A sample and an event are different shapes, so each gets its own registry: the two sample catalogs (metric_type, property_type) for samples, event_type for events. event_type describes every event key: (name, label, payload_schema, official, ...), with the official boolean (shipped-canonical versus org-local) as the built governance column; the fuller template / org / official scope ladder is future design, shared with the sample registry (key scope). Declaring event types (call-started, cable-unplugged, command-issued) gives events a known schema, makes them inspectable, and is what a derivation rule targets when turning a raw log line into a registered event; raw lines live untyped in the log_line lane until then, and most never become events.
Events: caught, caused, derived, scheduled
Section titled “Events: caught, caused, derived, scheduled”An event arrives one of four ways; none is auto-manufactured from a value flip (a transition is already two consecutive sample rows, derivable by query).
- caught: a component publishes a structured occurrence natively (an xAPI Event channel, a webhook, an SNMP trap).
- caused: we issued a command, recorded as an event; this is what opens an intended sample.
Caught/caused/derived/scheduled is the event’s origin, a small vocabulary on the event table, not the same enum as sample provenance. What keeps an event-driven system from rotting: events are declared (registered keys) and rules are inspectable (the blast-radius preview in the UI).
Storage
Section titled “Storage”The event row is the semantic-occurrence log; event_type is its key registry. Physical layout (partitioning, the owner arc, lineage) lives on storage.
There is no alarm_id column today; the event-carries-its-alarm edge is design direction. The lineage columns (ADR-0066) name what produced the event; the flat correlation_id threads the causal chain.
| Column | Type | Constraints | Notes |
|---|---|---|---|
id | bigint | PK | |
ts | timestamp with time zone | not null, default now() | |
owner_kind | text | not null | |
instance | text | not null, default ''::text | The sub-entity the occurrence is about, when the owner is not enough |
message | text | not null, default ''::text | |
attributes | jsonb | ||
provenance | text | not null, default 'observed'::text | |
source | text | not null, default ''::text | |
source_rule | text | ||
source_rule_version | bigint | ||
component_id | uuid | FK → component.id | |
system_id | uuid | FK → system.id | |
location_id | uuid | FK → location.id | |
node_id | uuid | FK → node.principal_id | |
event_type_id | uuid | FK → event_type.id, not null | The registered key this occurrence asserts |
origin | text | not null, default 'caught'::text | How the event arrived: caught, caused, derived, or scheduled |
source_event_id | bigint | FK → event.id | Lineage: the parent event, when one event caused another |
correlation_id | text | Threads the causal chain flat, across lineage hops | |
source_log_line_id | bigint | FK → log_line.id | Lineage: the raw log line a derivation rule promoted |
derived_by_rule_id | uuid | Lineage: the rule that did the deriving; a natively-caught event has none |
CHECK constraints and unique indexes on event
-
event_origin_check:CHECK ((origin = ANY (ARRAY['caught'::text, 'caused'::text, 'derived'::text, 'scheduled'::text]))) -
event_owner_arc_check:CHECK ((((owner_kind = 'component'::text) AND (component_id IS NOT NULL) AND (system_id IS NULL) AND (location_id IS NULL) AND (node_id IS NULL)) OR ((owner_kind = 'system'::text) AND (system_id IS NOT NULL) AND (component_id IS NULL) AND (location_id IS NULL) AND (node_id IS NULL)) OR ((owner_kind = 'location'::text) AND (location_id IS NOT NULL) AND (component_id IS NULL) AND (system_id IS NULL) AND (node_id IS NULL)) OR ((owner_kind = 'node'::text) AND (node_id IS NOT NULL) AND (component_id IS NULL) AND (system_id IS NULL) AND (location_id IS NULL)))) -
event_owner_kind_check:CHECK ((owner_kind = ANY (ARRAY['component'::text, 'system'::text, 'location'::text, 'node'::text]))) -
event_provenance_check:CHECK ((provenance = ANY (ARRAY['observed'::text, 'calculated'::text, 'intended'::text, 'declared'::text])))
| Column | Type | Constraints | Notes |
|---|---|---|---|
id | uuid | PK, default uuidv7() | |
name | text | not null | |
label | text | ||
description | text | not null, default ''::text | |
payload_schema | jsonb | The JSON Schema an occurrence of this key promises its attributes satisfy | |
official | boolean | not null, default false | Shipped-canonical versus org-local; official rows are read-only |
registered_at | timestamp with time zone | not null, default now() |
CHECK constraints and unique indexes on event_type
-
event_type_name_key:CREATE UNIQUE INDEX event_type_name_key ON public.event_type USING btree (name)
Related: calculations (the event_rule), alarms and actions, samples, and the glossary.