state

package
v0.0.0-...-6ed2b60 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package state owns the agent's authoritative cumulative counters, keyed by bpf.FlowKey — the staging area between the scraper, which feeds raw kernel readings, and the metrics Collector, which emits cumulatives to Prometheus.

Three invariants a caller must not break:

  • Delta math compares the entry-identity stamp, never counter magnitudes. See GlobalState.ApplyDelta.
  • A row whose attribution is about to change or die is folded via GlobalState.Settle first, or its whole history re-buckets at the next scrape.
  • Every reader takes one lock across live rows AND settled buckets. A snapshot torn across a fold double-counts or drops the bytes.

docs/architecture/contracts.md#required-contracts

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddDelta

func AddDelta(total, lastRaw *uint64, current uint64)

AddDelta integrates a raw counter into a cumulative total. current < lastRaw is treated as a kernel-side reset: the new current is itself the delta, not (max_u64 − lastRaw + current) (Implementation Contract #5, the u64 wraparound guard). Exported so the UnresolvedBuffer (internal/unresolved) computes per-scrape deltas for buffered flows with the identical guard rather than a second copy that could drift.

Types

type Counter

type Counter struct {
	// Total is the agent-side cumulative — bytes and packets since
	// the flow was first observed, surviving kernel evictions and,
	// once a WAL is in place, agent restarts.
	Total bpf.FlowMetrics
	// LastEbpfRaw is the most recent raw value read from the kernel.
	// The next ApplyDelta computes Δ = current − LastEbpfRaw, then
	// updates LastEbpfRaw to current.
	LastEbpfRaw bpf.FlowMetrics
}

Counter holds the per-flow cumulative state plus the last raw kernel reading needed for delta math. Mutated in place by GlobalState.ApplyDelta while the write lock is held.

type Entry

type Entry struct {
	Key   bpf.FlowKey
	Total bpf.FlowMetrics
}

Entry is the value type emitted by GlobalState.Snapshot: a (key, cumulative) pair safe to use after the RLock is released.

type GlobalState

type GlobalState struct {
	// contains filtered or unexported fields
}

GlobalState is the agent's authoritative flow-keyed counter store plus the settled-bytes accumulators that keep an exposed series monotone after its flows stop resolving. All maps live under one mutex: Settle moves value between them, and a reader that saw only one side would lose or double-count the folded bytes.

docs/architecture/data-structures.md#settled-bytes

func New

func New() *GlobalState

New returns an empty GlobalState.

func (*GlobalState) Add

func (g *GlobalState) Add(key bpf.FlowKey, m bpf.FlowMetrics)

Add folds m into key's cumulative without delta math, for already-computed totals (the UnresolvedBuffer's fold to "unknown"). It never touches LastEbpfRaw, so a key only ever passed to Add stays monotone. Never mix Add and ApplyDelta on one key.

docs/architecture/data-structures.md#userspace-structures

func (*GlobalState) ApplyDelta

func (g *GlobalState) ApplyDelta(key bpf.FlowKey, raw bpf.FlowMetrics)

ApplyDelta integrates a raw kernel reading for one flow key. First sight of a key sets Total=LastEbpfRaw=raw (no delta). Subsequent readings increment Total by current−lastRaw, treating current<lastRaw as a kernel-side reset where current itself is the delta (Implementation Contract #5).

Hot path: zero allocations after the first sighting of each key.

func (*GlobalState) Len

func (g *GlobalState) Len() int

Len returns the number of distinct flows currently tracked.

func (*GlobalState) PruneServerSettled

func (g *GlobalState) PruneServerSettled(alive map[string]struct{}) int

PruneServerSettled drops buckets whose ServerID is not in alive — a server's series ends when it leaves the Nova list, never on a TTL. alive MUST come from a successful, non-empty Nova fetch; pruning on missing data ends live servers' series. Returns buckets dropped.

docs/architecture/data-structures.md#settled-bytes

func (*GlobalState) PruneTenantSettled

func (g *GlobalState) PruneTenantSettled(alive map[string]struct{}) int

PruneTenantSettled releases buckets absent from alive — a settle-to-parent, not a delete: each dying bucket folds into the total absorber or lachesis_bytes_total dips. alive MUST come from a successful, non-empty Keystone fetch and MUST include metadata.UnknownTenantID.

docs/architecture/data-structures.md#settled-bytes

func (*GlobalState) Resolve

func (g *GlobalState) Resolve(key bpf.FlowKey, total, lastRaw bpf.FlowMetrics)

Resolve credits a late-bound flow whose MAC just became known: it folds the buffer's accumulated total in and sets LastEbpfRaw to lastRaw. Omitting that write-back is the classic double-count — the next ApplyDelta re-counts everything total already captured.

docs/architecture/data-structures.md#userspace-structures

func (*GlobalState) Restore

func (g *GlobalState) Restore(records []Record)

Restore seeds the map from records previously written to the WAL. Intended to run once at boot before any scraper or collector goroutine starts; takes the write lock defensively. Existing keys are overwritten, matching the "WAL is the source of truth on boot" contract.

func (*GlobalState) RestoreServerSettled

func (g *GlobalState) RestoreServerSettled(records []ServerSettledRecord)

RestoreServerSettled seeds the server-settled accumulator from records previously written to the WAL. Same contract as GlobalState.Restore: boot-time only, existing buckets overwritten.

func (*GlobalState) RestoreTenantSettled

func (g *GlobalState) RestoreTenantSettled(records []TenantSettledRecord)

RestoreTenantSettled seeds the settled accumulator from records previously written to the WAL. Same contract as GlobalState.Restore: boot-time only, existing buckets overwritten.

func (*GlobalState) RestoreTotalSettled

func (g *GlobalState) RestoreTotalSettled(records []TotalSettledRecord)

RestoreTotalSettled seeds the total-settled accumulator from records previously written to the WAL. Same contract as GlobalState.Restore: boot-time only, existing buckets overwritten.

func (*GlobalState) ServerSettledLen

func (g *GlobalState) ServerSettledLen() int

ServerSettledLen returns the number of server-settled buckets held.

func (*GlobalState) Settle

func (g *GlobalState) Settle(mode SettleMode, resolve func(bpf.FlowKey) (tenant, extNet, server string, ok bool)) int

Settle folds every resolvable row into the settled accumulators and evicts or rebases it per mode, in ONE critical section so the exposed aggregate never changes across the fold. Call it at the last moment the attribution is knowable. extNet must already be the gated label.

docs/architecture/contracts.md#required-contracts

func (*GlobalState) Snapshot

func (g *GlobalState) Snapshot(dst []Entry) []Entry

Snapshot appends every (key, Total) pair to dst and returns the resulting slice. Reusing the prior return value keeps steady-state allocations at zero; capacity grows only when the flow count exceeds the prior peak.

Holds the RLock for the full iteration (Implementation Contract #2).

func (*GlobalState) SnapshotForWAL

func (g *GlobalState) SnapshotForWAL(flows []Record, settled []TenantSettledRecord, serverSettled []ServerSettledRecord, totalSettled []TotalSettledRecord) ([]Record, []TenantSettledRecord, []ServerSettledRecord, []TotalSettledRecord)

SnapshotForWAL appends flows and settled buckets under ONE RLock; same reuse contract as GlobalState.Snapshot. The combined walk is for atomicity against Settle, as in GlobalState.SnapshotWithSettled — a torn WAL snapshot persists the folded bytes twice or not at all, and a crash makes that permanent. Values are copied out, so records outlive the RLock.

func (*GlobalState) SnapshotWithSettled

func (g *GlobalState) SnapshotWithSettled(flows []Entry, settled []TenantSettledRecord, serverSettled []ServerSettledRecord, totalSettled []TotalSettledRecord) ([]Entry, []TenantSettledRecord, []ServerSettledRecord, []TotalSettledRecord)

SnapshotWithSettled appends live flows and settled buckets under ONE RLock — the Collector's read path. Two snapshots would let a concurrent fold move value between them, double-counting or dropping the bytes for that exposure. Both slices follow the GlobalState.Snapshot reuse contract.

func (*GlobalState) TenantSettledLen

func (g *GlobalState) TenantSettledLen() int

TenantSettledLen returns the number of settled buckets currently held.

func (*GlobalState) TotalSettledLen

func (g *GlobalState) TotalSettledLen() int

TotalSettledLen returns the number of total-settled buckets held.

type Record

type Record struct {
	Key     bpf.FlowKey
	Counter Counter
}

Record is the (Key, Counter) pair the WAL round-trips. The Counter carries both Total and LastEbpfRaw, so a restored state computes deltas against the kernel's next reading without re-baselining.

INVARIANT — no kernel-internal identifiers in the WAL. FlowKey is deliberately free of the u32 tenant_id, which is re-interned every boot; adding any such ID re-keys the flow on restart and it never merges with post-restart traffic.

type ServerSettledKey

type ServerSettledKey struct {
	ServerID string
	Tenant   string
	ExtNet   string
	Zone     bpf.ZoneCode
	Dir      bpf.Direction
}

ServerSettledKey identifies one server-settled bucket. Unlike TenantSettledKey it KEEPS the server dimension — it is exactly the lachesis_server_bytes_total tuple, which is what makes a server's series monotone across a lost port or a re-created NIC. Released when the server leaves the Nova list.

docs/architecture/billing.md

type ServerSettledRecord

type ServerSettledRecord struct {
	Key     ServerSettledKey
	Bytes   uint64
	Packets uint64
}

ServerSettledRecord is one server-settled bucket's cumulative totals, emitted by the snapshot methods and round-tripped through the WAL (additive schema v4). Like TenantSettledRecord it carries no delta-math or recency fields.

type SettleMode

type SettleMode int

SettleMode selects what GlobalState.Settle does with a flow row after folding its Total into the settled accumulator. The right mode is decided by whether the row's kernel telemetry_map counters still exist — see the constants.

const (
	// SettleEvict deletes the folded row. Correct when the flow's
	// kernel counters are already gone (the ghost sweep deletes them
	// first), so nothing will feed the row again: a later reappearance
	// of the same key is a genuinely new flow whose kernel counter
	// restarts at zero and must re-baseline from first sight.
	SettleEvict SettleMode = iota
	// SettleRebase zeroes the folded row's Total but keeps the row and
	// its LastEbpfRaw. Correct when the kernel counters live on (a live
	// port changed tenant): the next ApplyDelta must count only bytes
	// arriving after the fold, not re-count the kernel cumulative that
	// was just settled.
	SettleRebase
)

type TenantSettledKey

type TenantSettledKey struct {
	Tenant string
	ExtNet string
	Zone   bpf.ZoneCode
	Dir    bpf.Direction
}

TenantSettledKey identifies one settled bucket. It is exactly the tenant tier's metric label tuple, so a fold lands in the same series the live flows occupied. ExtNet must already be the gated label.

type TenantSettledRecord

type TenantSettledRecord struct {
	Key     TenantSettledKey
	Bytes   uint64
	Packets uint64
}

TenantSettledRecord is one settled bucket's cumulative totals, emitted by the snapshot methods and round-tripped through the WAL. TenantSettled buckets carry no LastEbpfRaw — they are past delta math by definition — and no LastSeenNs — recency belongs to live flows.

type TotalSettledKey

type TotalSettledKey struct {
	ExtNet string
	Zone   bpf.ZoneCode
	Dir    bpf.Direction
}

TotalSettledKey identifies one total-settled bucket. The total family is DERIVED from the tenant tier, so a released tenant bucket folds here instead of vanishing — otherwise the immortal total series would decrease. Bounded by construction: zones × external networks × 2.

docs/architecture/billing.md

type TotalSettledRecord

type TotalSettledRecord struct {
	Key     TotalSettledKey
	Bytes   uint64
	Packets uint64
}

TotalSettledRecord is one total-settled bucket's cumulative totals, emitted by the snapshot methods and round-tripped through the WAL (additive schema v5). Like TenantSettledRecord it carries no delta-math or recency fields.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL