Event log schema reference
This page is a systematic reference for the on-disk/on-wire shape of the event log: the envelope every codec wraps a fact in, and every payload type the log can carry. For the concepts behind event sourcing in jaque, see Event sourcing instead.
The envelope
Section titled “The envelope”Every persisted event is a Payload plus the fields the log itself owns —
Envelope in eventlog/envelope.go:
| Field | Type | Meaning |
|---|---|---|
Version |
int |
Envelope version, bumped only for envelope-shape changes. Currently 2. |
Seq |
uint64 |
Assigned by the transport on append; 0 until then. |
Epoch |
uint64 |
The membership epoch the appending engine held at append time. |
Payload |
Payload |
The domain fact itself — one of the types below. |
The default codec (codec/, eventlog/codec_json.go) frames the
envelope, payload included, as one JSON object per line:
{"v":2,"type":"state_changed","seq":42,"epoch":1,"object_id":"web1/http","occurred_at":"2026-08-04T10:00:00Z","data":{...}}Short, snake_case keys — v, type, seq, epoch (omitted when zero),
object_id, occurred_at, data — because this is a public contract
read by jq and by ClickHouse, not Go field names leaking through
encoding/json’s default. type is the wire discriminator; a codec other
than JSON is free to use a different discriminator shape (an integer tag,
a protobuf oneof) — nothing above is JSON-specific except the object
itself.
Payload types
Section titled “Payload types”One row per type defined in eventlog/payload_*.go. Every payload
implements ObjectID() state.ObjectID and OccurredAt() time.Time;
ObjectID() is the zero state.ObjectID for the two reload events, which
are not about one object.
| Type | Wire type |
Emitted when | Key fields |
|---|---|---|---|
StateChanged |
state_changed |
Status, Type, Attempt, or Flapping changed on an object. |
ID, From state.State, To state.State, At |
ReachabilityChanged |
reachability_changed |
Once per object returned by graph.Reachability.SetHostDown. |
ID, Reachable bool, At |
CheckExecuted |
check_executed |
Every completed check. | Result state.CheckResult, Origin (active/passive/stale) |
NotificationRequested |
notification_requested |
Before any delivery attempt — the intent to notify is durable before the attempt exists. | ID, NotificationID, Kind state.NotifyKind, Level, Contacts []string, At |
NotificationSent |
notification_sent |
Delivery for a prior NotificationRequested succeeds. |
ID, NotificationID, Contact, At |
NotificationFailed |
notification_failed |
A delivery attempt for a prior NotificationRequested fails. |
ID, NotificationID, Contact, Attempt, Err string, Terminal bool, At |
AcknowledgementSet |
acknowledgement_set |
Operator runs ACKNOWLEDGE_HOST_PROBLEM/ACKNOWLEDGE_SVC_PROBLEM. |
ID, Author, Comment, Sticky bool, At |
AcknowledgementCleared |
acknowledgement_cleared |
Operator runs REMOVE_HOST_ACKNOWLEDGEMENT/REMOVE_SVC_ACKNOWLEDGEMENT. |
ID, Author, At |
DowntimeScheduled |
downtime_scheduled |
Operator runs SCHEDULE_HOST_DOWNTIME/SCHEDULE_SVC_DOWNTIME. |
ID, DowntimeID string, Author, Comment, Start, End, At |
DowntimeCancelled |
downtime_cancelled |
Operator runs DEL_HOST_DOWNTIME/DEL_SVC_DOWNTIME. |
ID, DowntimeID string, At |
ConfigReloaded |
config_reloaded |
A SIGHUP-triggered reload applies successfully. | Added, Removed, Changed, Unchanged int, At (no ID) |
ConfigReloadRejected |
config_reload_rejected |
A SIGHUP-triggered reload fails validation; the old config keeps running. | Err string, At (no ID) |
ObjectRetired |
object_retired |
A reload removes an object from the config. | ID, At |
Why the archive is readable without jaque
Section titled “Why the archive is readable without jaque”Every field above is a plain string, number, bool, or timestamp — no
opaque blob, no jaque-internal type leaking onto the wire — and the
codec is the only thing that knows how to turn a Payload into bytes, so
the shape above is the format, not an approximation of it. That is what
lets the archive sink hand its
zstd-compressed JSON lines to jq, ClickHouse, or DuckDB directly: reading
the log back never requires running jaque or linking against its code,
only knowing the table above.