progress

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2026 License: MIT Imports: 14 Imported by: 0

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

View Source
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

func HumanBytes(n int64) string

HumanBytes formats a byte count in human-readable units (KiB/MiB/GiB/TiB).

func HumanDollars

func HumanDollars(d float64) string

HumanDollars formats a dollar amount, switching from 4-decimal to 2-decimal at the cent boundary.

func HumanRate

func HumanRate(r float64) string

HumanRate formats a per-second rate with K/M/G suffixes. Falls back to a plain integer with no suffix below 1000.

func Percent

func Percent(x float64, cap int) int

Percent returns the integer-rounded percentage of x against the cap.

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

func RunPlainReporter(w io.Writer, p *Progress, done <-chan struct{}, interval time.Duration)

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

func RunScanUI(p *Progress, done <-chan struct{}, sampleInterval, uiInterval time.Duration)

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

func StartSampler(p *Progress, interval time.Duration) func()

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

func New(region string, maxWorkers int) *Progress

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

func (p *Progress) BeginRequest() time.Time

BeginRequest marks the start of one ListObjectsV2 round-trip. The caller passes the returned start time back to EndRequest.

func (*Progress) EndRequest

func (p *Progress) EndRequest(start time.Time)

EndRequest finalises one round-trip: drops the inflight counter, increments listRequests, and adds duration to the total accumulator.

func (*Progress) ObserveBatch

func (p *Progress) ObserveBatch(objs []radix.Object)

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

func (p *Progress) SetQueueDepthFn(f func() int)

SetQueueDepthFn registers a callback returning the current length of the scanner's work queue. Invoked once per Snapshot.

func (*Progress) Snapshot

func (p *Progress) Snapshot() Snapshot

Snapshot copies the current counters into a value the caller can read without further synchronization.

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

func (s Snapshot) CumulativeParallelism() float64

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) ListCost

func (s Snapshot) ListCost() float64

ListCost returns the cumulative LIST cost in dollars.

func (Snapshot) MonthlyStorageCost

func (s Snapshot) MonthlyStorageCost() float64

MonthlyStorageCost returns the per-month storage cost summed over all observed classes.

func (Snapshot) TotalBytes

func (s Snapshot) TotalBytes() int64

TotalBytes returns the sum of all per-class bytes.

Jump to

Keyboard shortcuts

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