Documentation
¶
Overview ¶
Package progress aggregates the live scan/load metrics (atomic counters, EWMAs) and the bubbletea dashboards that visualise them. Importers see a single public surface — progress.Progress, progress.Snapshot, progress.RunScanUI, progress.RunIO — instead of three top-level files cluttering the main package.
Index ¶
- Constants
- func HumanBytes(n int64) string
- func HumanDollars(d float64) string
- func HumanRate(r float64) string
- func Percent(x float64, cap int) int
- func ReportIO(w io.Writer, label string, counter *atomic.Int64, done <-chan struct{}, ...)
- func RunIO(label string, counter *atomic.Int64, total int64, interval time.Duration, ...) error
- func RunPlainReporter(w io.Writer, p *Progress, done <-chan struct{}, interval time.Duration)
- func RunScanUI(p *Progress, done <-chan struct{}, sampleInterval, uiInterval time.Duration)
- func StartSampler(p *Progress, interval time.Duration) func()
- type Progress
- type Snapshot
Constants ¶
const NumStorageClasses = 16
NumStorageClasses is the size of the per-class counter array. It must be at least one greater than the highest StorageClass enum value defined in the radix package.
Variables ¶
This section is empty.
Functions ¶
func HumanBytes ¶
HumanBytes formats a byte count in human-readable units (KiB/MiB/GiB/TiB).
func HumanDollars ¶
HumanDollars formats a dollar amount, switching from 4-decimal to 2-decimal at the cent boundary.
func HumanRate ¶
HumanRate formats a per-second rate with K/M/G suffixes. Falls back to a plain integer with no suffix below 1000.
func ReportIO ¶
func ReportIO(w io.Writer, label string, counter *atomic.Int64, done <-chan struct{}, interval time.Duration)
ReportIO ticks every interval and prints a one-line "\r"-anchored progress indicator with the cumulative bytes through the counter and the rate observed between consecutive ticks. On done close it prints the final summary and returns. Used as the non-TTY fallback by RunIO.
func RunIO ¶
func RunIO(label string, counter *atomic.Int64, total int64, interval time.Duration, work func() error) error
RunIO executes work in a goroutine while a bubbletea dashboard tracks counter (and total, when non-zero) on stderr. Falls back to ReportIO's plain "\r-line" reporter when stderr is not a TTY so log redirection doesn't get an ANSI rendering. Returns whatever work returned.
func RunPlainReporter ¶
RunPlainReporter is the redirected-output fallback: one line per tick, terminated with \r so a TTY still updates in place while a log file gets each line separately.
func RunScanUI ¶
RunScanUI renders a live scanner dashboard to stderr until done is closed. The bubbletea program runs inline (no alt-screen) and clears its rendered area on quit so subsequent stderr writes flow normally below.
A side goroutine keeps the EWMA fresh on its own cadence (sampleInterval) independent of the UI tick rate so a -progress-ms tweak doesn't skew the effective-parallelism math.
On non-TTY stderr (log redirection) the function falls back to a plain printf-per-tick loop — bubbletea TUI output would otherwise turn into ANSI noise inside the log file.
func StartSampler ¶
StartSampler runs Progress.SampleInflight on a fixed cadence and returns a stopper that joins the sampler goroutine.
Types ¶
type Progress ¶
type Progress struct {
// contains filtered or unexported fields
}
Progress holds atomic counters that workers and the discoverer update as they observe S3 ListObjectsV2 responses. Read-side consumers (the TTY reporter, the TUI status bar) snapshot with Snapshot.
func New ¶
New returns a zero-state Progress tracking storage in the given AWS region (used by the cost calculator). maxWorkers is the configured upper bound on concurrent ListObjectsV2 workers; used for display only.
func (*Progress) BeginRequest ¶
BeginRequest marks the start of one ListObjectsV2 round-trip. The caller passes the returned start time back to EndRequest.
func (*Progress) EndRequest ¶
EndRequest finalises one round-trip: drops the inflight counter, increments listRequests, and adds duration to the total accumulator.
func (*Progress) ObserveBatch ¶
ObserveBatch tallies a batch of objects into the running counters.
func (*Progress) SampleInflight ¶
func (p *Progress) SampleInflight()
SampleInflight folds three measurements into their EWMAs in one pass: the instantaneous inflight count, and the per-second rates of new objects and list requests observed since the last sample. Must be called from a single goroutine (the reporter); writers are lock-free.
alpha = 1 - exp(-dt / tau) ewma += alpha * (sample - ewma)
func (*Progress) SetQueueDepthFn ¶
SetQueueDepthFn registers a callback returning the current length of the scanner's work queue. Invoked once per Snapshot.
type Snapshot ¶
type Snapshot struct {
Region string
MaxWorkers int
Elapsed time.Duration
ListRequests int64
ObjectsSeen int64
Inflight int64
InflightEWMA float64
ObjectsPerSec float64
RequestsPerSec float64
ObjectsPerList float64
TotalRequestNanos int64
QueueDepth int
BytesByClass [NumStorageClasses]int64
ObjectsByClass [NumStorageClasses]int64
}
Snapshot is a point-in-time copy of the counters, safe to format without further locking.
func (Snapshot) CumulativeParallelism ¶
CumulativeParallelism is the lifetime-average effective parallelism derived from Little's Law: total request time divided by elapsed wall time. Used for the final scan summary.
func (Snapshot) MonthlyStorageCost ¶
MonthlyStorageCost returns the per-month storage cost summed over all observed classes.
func (Snapshot) TotalBytes ¶
TotalBytes returns the sum of all per-class bytes.