Documentation
¶
Overview ¶
Package imztop is a btop-style desktop resource monitor built on ImZero2 + egui2, consuming the in-repo `observability/sysmetrics` data layer. Wired as the imzero2 demo subcommand `appCode == 7`.
The package is read-only against sysmetrics. There is no process write-side (kill / nice / signal) by design — see ADR-0020 SD11.
Architecture ¶
One sampler goroutine owns a *sysmetrics.Bundle and ticks at SamplerOptions.UpdateInterval (default 1 s). Each tick it calls Bundle.Sample, appends the result to per-series ring buffers, then publishes a fresh PublishedSnapshot via atomic.Pointer. The egui frame loop reads the latest snapshot via atomic.Load and re-slices stable ring backing memory — no allocation on the hot path.
See also ¶
- doc/adr/0020-imzero2-imztop-resource-monitor.md — accepted decision and milestone plan.
- public/observability/sysmetrics/ — data source.
Index ¶
- type App
- type NamedSeries
- type NamedValue
- type ProcSortByE
- type PublishedSnapshot
- type Sampler
- func (inst *Sampler) Close() (err error)
- func (inst *Sampler) Interval() (d time.Duration)
- func (inst *Sampler) IntervalLabel() (out string)
- func (inst *Sampler) IsPaused() (p bool)
- func (inst *Sampler) Latest() (snap *PublishedSnapshot)
- func (inst *Sampler) Pause(p bool)
- func (inst *Sampler) Start(_ context.Context)
- type SamplerI
- type SamplerOptions
- type SlidingWindow
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App is the per-window imztop instance. The registry's factory ctor allocates a fresh App per Open() so two windows have independent UI state (currently just the selected network interface; more fields land here as user-visible per-window state grows).
func (*App) Frame ¶
func (inst *App) Frame(ctx app.FrameContextI) (err error)
Frame renders one frame of the imztop window body. The host has already pre-pushed a window-unique salt onto inst.ids via c.IdScope (windowhost.renderWindowBody), so widget ids derived from inst.ids are scoped under that salt — no further package-level coordination is needed (every render helper is a method on *App).
type NamedSeries ¶
NamedSeries is one labelled history series in a published snapshot (e.g. "sda" → read rates over the last 10 minutes). The slice is a fresh copy of the sampler's ring backing memory; mutating it does not affect future ticks.
type NamedValue ¶
NamedValue is a (key, value) pair for namedWindowSet.push.
type ProcSortByE ¶
type ProcSortByE uint8
ProcSortByE selects which column the process panel sorts on.
const ( // ProcSortByCPU keys on the EWMA-smoothed CPU% (sampler's // ProcCPUSmoothed slice). Default sort key: order is stable // across transient spikes, matching the column the heatmap palette // is tinted onto. ProcSortByCPU ProcSortByE = iota // ProcSortByCPURaw keys on the raw sampler-interval CPU% value. // Useful when the user is hunting transient spikes that the // smoothed view dampens. When selected, the raw column is tinted // instead of the smoothed one. ProcSortByCPURaw ProcSortByMem ProcSortByPID ProcSortByUser ProcSortByName )
type PublishedSnapshot ¶
type PublishedSnapshot struct {
SampledAtUnixMs int64
HistoryTimeUnixSec []float64
HistoryCPUTotal []float64
HistoryMemUsed []float64
HistoryDiskRead []float64 // MiB/s (sum across block devices)
HistoryDiskWrite []float64 // MiB/s
HistoryNetRx []float64 // MiB/s (sum across interfaces)
HistoryNetTx []float64 // MiB/s
HistoryBatteryPct []float64
HistoryCPUPerCore [][]float64 // [core][time] percent
HistoryGPUBusyPerDev [][]float64 // [device][time] percent
HistoryDiskReadByDev []NamedSeries // MiB/s per block device, ordered by name
HistoryDiskWriteByDev []NamedSeries // MiB/s per block device
HistoryNetRxByIface []NamedSeries // MiB/s per interface
HistoryNetTxByIface []NamedSeries // MiB/s per interface
LatestCPU *sysmsnap.CPUSnapshot
LatestMem *sysmsnap.MemSnapshot
LatestDisk *sysmsnap.DiskSnapshot
LatestNet *sysmsnap.NetSnapshot
LatestBattery *sysmsnap.BatterySnapshot
LatestGPU *sysmsnap.GPUSnapshot
LatestContainer *sysmsnap.ContainerInfo
LatestPSI *sysmsnap.PSISnapshot
Sensors []sysmsnap.TempReading
Procs []sysmsnap.ProcInfo
// ProcCPUSmoothed is the per-process EWMA-smoothed CPU% (α=
// procCPUEWMAAlpha), parallel to Procs by index. Drives the
// process-table sort key and the CPU%-cell background tint;
// the raw Procs[i].CPUPercent stays untouched so the displayed
// value still reflects the latest sampler-interval average.
// Smoothing is per-PID and persists across ticks via the
// Sampler's procCPUEWMA map (evicted when a PID disappears).
ProcCPUSmoothed []float32
// Topology is the static CPU containment hierarchy, delivered on the metric
// plane (ADR-0090 SD6) rather than read in-process by the consumer. nil until
// the first topology-bearing snapshot arrives (or if the scraper could not
// read it); the topology panel builds its treemap from it once.
Topology *sysmsnap.Topology
Errors map[sysmsnap.Domain]error
}
PublishedSnapshot is the read-only frame the renderer consumes. Built once per Sampler tick and replaced atomically; slices are owned by the snapshot and never mutated after publication, so concurrent readers see a coherent view.
All byte/sec history fields (disk/net) are stored in MiB/s so the renderer can label plot axes "MiB/s" without per-frame scaling. Sub-MiB/s rates appear as small fractional values; raw counters at the byte level remain available on the Latest* fields.
type Sampler ¶
type Sampler struct {
// contains filtered or unexported fields
}
Sampler runs a goroutine that periodically calls Bundle.Sample and publishes a PublishedSnapshot via atomic.Pointer.
func NewSampler ¶
func NewSampler(opts SamplerOptions, bus app.BusI) (inst *Sampler, err error)
NewSampler builds a pure-consumer Sampler (ADR-0090): it subscribes to the system-metrics plane on the host-provided bus and folds what arrives into sliding-window history + per-process EWMA. The /proc reader is a separate scraper (the carousel host's co-located one, the tour's, or an external sysmetricsd), so imztop builds no collectors and holds no system-state capability. bus is MountCtx.Bus() in the app; tests and the tour pass an inprocbus client fed by StartScraper. A nil bus degrades to NoopBus.
func (*Sampler) Interval ¶
Interval returns the most recent observed sample cadence (the scraper's real rate; see intervalNs). There is no setter — imztop does not control the cadence; it observes it from consecutive samples (ADR-0090 SD5).
func (*Sampler) IntervalLabel ¶
IntervalLabel returns the observed sample cadence as a short human-readable label for the top-bar status row (the scraper's real rate; see intervalNs).
func (*Sampler) Latest ¶
func (inst *Sampler) Latest() (snap *PublishedSnapshot)
type SamplerI ¶
type SamplerI interface {
Start(ctx context.Context)
Latest() (snap *PublishedSnapshot)
Pause(p bool)
IsPaused() (p bool)
Close() (err error)
}
SamplerI is the public surface a Sampler implements.
type SamplerOptions ¶
SamplerOptions configures a Sampler.
type SlidingWindow ¶
type SlidingWindow[T any] = slidingwindow.Window[T]
SlidingWindow aliases the shared observability sliding-window buffer, lifted out of imztop + imzrt per ADR-0061 SD13. See slidingwindow.Window for semantics (memmove-on-full, stable backing, per-tick copy-out; not safe for concurrent use).
func NewSlidingWindow ¶
func NewSlidingWindow[T any](capacity int32) *SlidingWindow[T]
NewSlidingWindow constructs a SlidingWindow holding at most capacity values (clamped to a minimum of 1).
Source Files
¶
- app_register.go
- doc.go
- imztop.go
- imztop_cpu_heatmap.go
- imztop_layout.go
- imztop_panel_battery.go
- imztop_panel_cpu.go
- imztop_panel_disk.go
- imztop_panel_gpu.go
- imztop_panel_mem.go
- imztop_panel_net.go
- imztop_panel_pressure.go
- imztop_panel_proc.go
- imztop_panel_procmap.go
- imztop_panel_sensors.go
- imztop_panel_topbar.go
- imztop_panel_topology.go
- imztop_procmap_tree.go
- imztop_rate_plot.go
- imztop_sampler.go
- imztop_sampler_keyed.go
- imztop_slidingwindow.go
- imztop_theme.go
- imztop_timeticks.go
- imztop_topology_tree.go
- imztop_tour.go
- imztop_tour_synth.go
- imztop_ytalbot.go