Documentation
¶
Overview ¶
Package forecast projects when a resource such as a disk will fill, using an ordinary least-squares line fit over (timestamp, bytes used) samples. Real usage rarely grows linearly, so the result is a rough estimate.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Point ¶
Point is one (timestamp, bytes used) observation. Timestamps need not be sorted or evenly spaced; Project sorts its own copy.
type Projection ¶
type Projection struct {
// SlopeBytesPerDay is the fitted line's slope: always > 0, since
// Project returns nil otherwise.
SlopeBytesPerDay float64
// DaysUntilFull is how many days from now the fitted line crosses
// TotalBytes, floored at 0 (never negative, even if the line has
// already crossed).
DaysUntilFull float64
// FullAt is now plus DaysUntilFull, the projected exhaustion
// timestamp.
FullAt time.Time
// CurrentUsedBytes is the fitted line's value at now, not the raw
// last sample, so a single noisy spike doesn't move the headline
// number.
CurrentUsedBytes float64
TotalBytes float64
SampleCount int
// Span is the time between the earliest and latest sample Project
// fit the line over.
Span time.Duration
}
Projection is Project's result for one resource: a real, growing trend with a projected exhaustion point. Project returns nil instead of a Projection when the trend is flat, improving, or under-sampled, so a nil result always means "nothing to warn about," never "zero days left."
func Project ¶
func Project(points []Point, totalBytes float64, now time.Time) *Projection
Project fits an ordinary-least-squares line through points and projects it forward to totalBytes. Returns nil when there isn't enough history (fewer than minPoints samples, or less than minSpan between the earliest and latest), when totalBytes isn't a real capacity figure (<= 0), or when the fitted slope is zero or negative: an operator should never be warned about a trend that isn't actually pointing at exhaustion, even if the raw samples are noisy around a flat average.
Example ¶
package main
import (
"fmt"
"time"
"github.com/GLINCKER/levelrail/kit/forecast"
)
func main() {
start := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
const gib = 1 << 30
var points []forecast.Point
for day := 0; day < 7; day++ {
points = append(points, forecast.Point{
Timestamp: start.AddDate(0, 0, day),
UsedBytes: float64(10+day*5) * gib,
})
}
now := start.AddDate(0, 0, 6)
p := forecast.Project(points, 100*gib, now)
fmt.Printf("growing %.0f GiB/day, full in %.0f days\n", p.SlopeBytesPerDay/gib, p.DaysUntilFull)
}
Output: growing 5 GiB/day, full in 12 days