Documentation
¶
Overview ¶
Package sysmtee writes the system-metrics plane into `boxer.facts`.
It is ADR-0090 P5 — the persistence tee reserved when the plane was designed and left unbuilt until something wanted history — in the shape ADR-0184 settles: a subscriber, not a fork of the producer. It consumes the same bundles any other consumer sees and writes them through the generated record store in github.com/stergiotis/boxer/public/keelson/runtime/sysmfacts. Producer and consumers are untouched by its presence.
It re-models rather than tees bytes ¶
ADR-0090 §SD4 anticipated a tee that forwarded the wire bytes unchanged, which was possible while the wire was expected to be the facts codec. The plane shipped a CBOR codec instead and the swap never happened, so this decodes to github.com/stergiotis/boxer/public/observability/sysmetrics/sysmsnap structs and builds rows from them. That is the honest cost of the interim codec, not a design choice made here.
Losing samples is preferred to blocking the plane ¶
The bus delivers on its own goroutine and a record store is single-goroutine, so bundles hand off to an owner goroutine through a bounded queue. When the queue is full — ClickHouse slow or down — the incoming bundle is dropped and counted rather than blocking delivery. The metric plane is one-way and unacknowledged by design (ADR-0090 §SD4 rejects JetStream for it), so a gap in stored history is the correct failure: the alternative is a stalled subscription that also delays every other consumer on an in-process bus.
Append-only ¶
Every kind is append-shaped and the store has no state view to misuse — see github.com/stergiotis/boxer/public/keelson/runtime/sysmfacts. Re-writing a descriptor row is therefore harmless, which is what makes "on first sight of a host" a cheap heuristic rather than a correctness requirement.
Index ¶
Constants ¶
const ( DefaultQueueDepth = 64 DefaultFlushInterval = 10 * time.Second DefaultFlushRows = 256 )
Defaults for Options. The flush interval is the dominant one: it is the window of samples lost if the process dies, and the rate at which small inserts reach ClickHouse.
Variables ¶
var PackageProps = packageprops.Props{ WASMWASI: packageprops.WASMBlocked, WASMJS: packageprops.WASMBlocked, WASMFreestanding: packageprops.WASMBlocked, }
PackageProps records this package's curated properties (ADR-0080). Blocked: it composes the generated record store, which pulls in the arrow and ClickHouse-executor stack.
Functions ¶
This section is empty.
Types ¶
type Options ¶
type Options struct {
// Bus is the metric plane to subscribe on — the same client the scraper
// publishes through when co-located.
Bus app.BusI
// Store is the facts-bound record store rows are written to. The tee takes
// ownership: it is used only from the tee's own goroutine, satisfying the
// single-goroutine contract, and Close is the caller's after Stop returns.
Store *sysmfacts.SysmetricsStore
// Host is the token stored on every row.
//
// It is configured rather than read from the message because the host lives
// in the subject and [sysmetricsbus.ConsumerOptions.Handler] receives only
// the snapshot. A tee co-located with its scraper knows the token; a
// standalone sink subscribing to several hosts would need the subject in
// the handler, which is a sysmetricsbus change deferred until such a sink
// exists (ADR-0184 §SD8).
Host string
// Subject defaults to this host's bundle subject. Set it to the wildcard
// only when every publisher on it is the host named above.
Subject string
// QueueDepth bounds the handoff between the bus goroutine and the writer.
// Zero takes DefaultQueueDepth.
QueueDepth int
// FlushInterval bounds how long a row waits before becoming durable. Zero
// takes DefaultFlushInterval.
FlushInterval time.Duration
// FlushRows flushes early once this many rows are buffered, so a fast plane
// does not build an unbounded batch between ticks. Zero takes
// DefaultFlushRows.
FlushRows int
// PersistProcCmd opts into storing process command lines, user names and
// uid/gid — the ADR-0090 §SD8 sensitive class, which
// [sysmfacts.SysProcCmd] keeps in its own kind.
//
// Off by default, and deliberately not merely a masking flag: §SD8's
// accepted exposure was scoped to a single-tenant, localhost-bound bus,
// where a command line lives as long as its subscriber. A row in
// `boxer.facts` outlives the process, is readable by anything with database
// access, and is backed up with everything else. The masking switch §SD8
// defers does not exist, so not writing is the only control that currently
// enforces anything.
//
// The rest of the process table — pids, names, cpu, memory, the ADR-0126
// topology marks — is stored either way.
PersistProcCmd bool
Log zerolog.Logger
}
Options configures a tee. Bus, Store and Host are required.
type Stats ¶
type Stats struct {
// Bundles received from the plane.
Bundles uint64
// Dropped bundles — the queue was full when they arrived.
Dropped uint64
// Rows handed to the store.
Rows uint64
// Flushed rows made durable.
Flushed uint64
// FlushErrors counts failed flushes. The store keeps the batch pending and
// the next flush reships it, so this is not a row-loss count.
FlushErrors uint64
}
Stats reports what the tee has done. Counters are cumulative and safe to read from any goroutine.