Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions capacity-forecast.go
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

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"`
Comment on lines +38 to +41
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this long/short/mid term trend? Describe it in one or two sentences.


GrowthRatePerDay int64 `json:"growthRatePerDay"`
DataPointCount int `json:"dataPointCount"`
Comment on lines +43 to +44
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is DataPointCount related to GrowthRatePerDay? So is it the difference between now and now-DataPointCount?

I feel these variables could be named better.


// 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"`
Comment on lines +54 to +57
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Percentage or bytes?


// 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
}
Loading