diff --git a/capacity-forecast.go b/capacity-forecast.go new file mode 100644 index 00000000..64811f47 --- /dev/null +++ b/capacity-forecast.go @@ -0,0 +1,87 @@ +// +// Copyright (c) 2015-2026 MinIO, Inc. +// +// This file is part of MinIO Object Storage stack +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package madmin + +import ( + "context" + "encoding/json" + "net/http" +) + +// CapacityForecast contains storage capacity predictions based on +// historical daily snapshots processed through a Kalman filter. +// +// Days-until-threshold fields are pointers: nil means "unknown" (for example, +// not enough history yet, or usage is not growing). A concrete value may be +// negative when the threshold was already crossed in the past. +type CapacityForecast struct { + CurrentUsedBytes uint64 `json:"currentUsedBytes"` + CurrentTotalBytes uint64 `json:"currentTotalBytes"` + CurrentUsedPercent float64 `json:"currentUsedPercent"` + + // Days until each usage threshold is reached. nil = unknown. + DaysUntil80Pct *float64 `json:"daysUntil80Pct,omitempty"` + DaysUntil90Pct *float64 `json:"daysUntil90Pct,omitempty"` + DaysUntil100Pct *float64 `json:"daysUntil100Pct,omitempty"` + + GrowthRatePerDay int64 `json:"growthRatePerDay"` + DataPointCount int `json:"dataPointCount"` + + // Worst-case prediction based on the largest single-day growth + // observed between any two consecutive data points. nil = unknown. + MinDaysUntilFull *float64 `json:"minDaysUntilFull,omitempty"` + + // Confidence from Kalman filter covariance (0-1, higher = more confident). + RSquared float64 `json:"rSquared"` + Variance float64 `json:"variance"` // variance of daily usedFraction deltas + + // Concrete min/max daily changes in usedFraction between consecutive + // data points. DayMinDelta can be negative (space was freed). + DayMinDelta float64 `json:"dayMinDelta"` + DayMaxDelta float64 `json:"dayMaxDelta"` + + // Recency-weighted predictions from the Kalman filter. + RecentGrowthRatePerDay float64 `json:"recentGrowthRatePerDay"` + RecentDaysUntilFull *float64 `json:"recentDaysUntilFull,omitempty"` +} + +// CapacityForecast returns a storage capacity forecast based on +// historical daily snapshots. +func (adm *AdminClient) CapacityForecast(ctx context.Context) (CapacityForecast, error) { + resp, err := adm.executeMethod(ctx, + http.MethodGet, + requestData{ + relPath: adminAPIPrefix + "/capacity-forecast", + }) + defer closeResponse(resp) + if err != nil { + return CapacityForecast{}, err + } + + if resp.StatusCode != http.StatusOK { + return CapacityForecast{}, httpRespToErrorResponse(resp) + } + + var f CapacityForecast + if err = json.NewDecoder(resp.Body).Decode(&f); err != nil { + return CapacityForecast{}, err + } + + return f, nil +}