|
|
@@ -383,6 +383,7 @@ func (a *Accesses) CustomPricingHasChanged() bool {
|
|
|
// by time period using window and offset, aggregation field and subfield (e.g. grouping by label.app
|
|
|
// using aggregation=label, aggregationSubfield=app), and filtered by namespace and cluster.
|
|
|
func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|
|
+
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
|
|
|
|
@@ -440,16 +441,11 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // if custom pricing has changed, then clear the cache and recompute data
|
|
|
- if a.CustomPricingHasChanged() {
|
|
|
- clearCache = true
|
|
|
- }
|
|
|
-
|
|
|
// clear cache prior to checking the cache so that a clearCache=true
|
|
|
// request always returns a freshly computed value
|
|
|
if clearCache {
|
|
|
- a.AggregateCache.Flush()
|
|
|
- a.CostDataCache.Flush()
|
|
|
+ A.AggregateCache.Flush()
|
|
|
+ A.CostDataCache.Flush()
|
|
|
}
|
|
|
|
|
|
// parametrize cache key by all request parameters
|
|
|
@@ -458,7 +454,7 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
|
|
|
allocateIdle, includeTimeSeries, includeEfficiency)
|
|
|
|
|
|
// check the cache for aggregated response; if cache is hit and not disabled, return response
|
|
|
- if result, found := a.AggregateCache.Get(aggKey); found && !disableCache {
|
|
|
+ if result, found := A.AggregateCache.Get(aggKey); found && !disableCache {
|
|
|
w.Write(WrapDataWithMessage(result, nil, fmt.Sprintf("aggregate cache hit: %s", aggKey)))
|
|
|
return
|
|
|
}
|
|
|
@@ -469,10 +465,10 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
|
|
|
|
|
|
// Use Thanos Client if it exists (enabled) and remote flag set
|
|
|
var pClient prometheusClient.Client
|
|
|
- if remote && a.ThanosClient != nil {
|
|
|
- pClient = a.ThanosClient
|
|
|
+ if remote && A.ThanosClient != nil {
|
|
|
+ pClient = A.ThanosClient
|
|
|
} else {
|
|
|
- pClient = a.PrometheusClient
|
|
|
+ pClient = A.PrometheusClient
|
|
|
}
|
|
|
|
|
|
// convert duration and offset to start and end times
|
|
|
@@ -485,7 +481,7 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
|
|
|
durationHours := endTime.Sub(*startTime).Hours()
|
|
|
|
|
|
threeHoursAgo := time.Now().Add(-3 * time.Hour)
|
|
|
- if a.ThanosClient != nil && endTime.After(threeHoursAgo) {
|
|
|
+ if A.ThanosClient != nil && endTime.After(threeHoursAgo) {
|
|
|
klog.Infof("Setting end time backwards to first present data")
|
|
|
*endTime = time.Now().Add(-3 * time.Hour)
|
|
|
}
|
|
|
@@ -509,6 +505,9 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
|
|
|
}
|
|
|
resolutionDuration, err := ParseDuration(resolution)
|
|
|
resolutionHours := resolutionDuration.Hours()
|
|
|
+ if resolutionHours < 1 {
|
|
|
+ resolutionHours = 1
|
|
|
+ }
|
|
|
if err != nil {
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
w.Write(WrapData(nil, fmt.Errorf("Error parsing resolution (%s)", resolution)))
|
|
|
@@ -523,7 +522,7 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
|
|
|
// attempt to retrieve cost data from cache
|
|
|
var costData map[string]*CostData
|
|
|
key := fmt.Sprintf(`%s:%s:%s:%t`, duration, offset, resolution, remoteEnabled)
|
|
|
- cacheData, found := a.CostDataCache.Get(key)
|
|
|
+ cacheData, found := A.CostDataCache.Get(key)
|
|
|
if found && !disableCache {
|
|
|
ok := false
|
|
|
costData, ok = cacheData.(map[string]*CostData)
|
|
|
@@ -533,35 +532,40 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
|
|
|
} else {
|
|
|
start := startTime.Format(RFC3339Milli)
|
|
|
end := endTime.Format(RFC3339Milli)
|
|
|
- costData, err = a.Model.ComputeCostDataRange(pClient, a.KubeClientSet, a.Cloud, start, end, resolution, "", "", remoteEnabled)
|
|
|
+ costData, err = A.Model.ComputeCostDataRange(pClient, A.KubeClientSet, A.Cloud, start, end, resolution, "", "", remoteEnabled)
|
|
|
if err != nil {
|
|
|
w.Write(WrapData(nil, err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- a.CostDataCache.Set(key, costData, cache.DefaultExpiration)
|
|
|
+ A.CostDataCache.Set(key, costData, cache.DefaultExpiration)
|
|
|
}
|
|
|
|
|
|
- c, err := a.Cloud.GetConfig()
|
|
|
+ c, err := A.Cloud.GetConfig()
|
|
|
if err != nil {
|
|
|
w.Write(WrapData(nil, err))
|
|
|
return
|
|
|
}
|
|
|
- discount, err := parsePercentString(c.Discount)
|
|
|
+ discount, err := strconv.ParseFloat(c.Discount[:len(c.Discount)-1], 64)
|
|
|
if err != nil {
|
|
|
w.Write(WrapData(nil, err))
|
|
|
return
|
|
|
}
|
|
|
+ discount = discount * 0.01
|
|
|
|
|
|
idleCoefficients := make(map[string]float64)
|
|
|
|
|
|
if allocateIdle {
|
|
|
- windowStr := fmt.Sprintf("%dh", int(durationHours))
|
|
|
- if a.ThanosClient != nil {
|
|
|
+ idleDurationCalcHours := durationHours
|
|
|
+ if durationHours < 1 {
|
|
|
+ idleDurationCalcHours = 1
|
|
|
+ }
|
|
|
+ windowStr := fmt.Sprintf("%dh", int(idleDurationCalcHours))
|
|
|
+ if A.ThanosClient != nil {
|
|
|
klog.Infof("Setting offset to 3h")
|
|
|
offset = "3h"
|
|
|
}
|
|
|
- idleCoefficients, err = ComputeIdleCoefficient(costData, pClient, a.Cloud, discount, windowStr, offset, resolution)
|
|
|
+ idleCoefficients, err = ComputeIdleCoefficient(costData, pClient, A.Cloud, discount, windowStr, offset, resolution)
|
|
|
if err != nil {
|
|
|
klog.Errorf("error computing idle coefficient: windowString=%s, offset=%s, err=%s", windowStr, offset, err)
|
|
|
w.Write(WrapData(nil, err))
|
|
|
@@ -608,8 +612,8 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
|
|
|
ResolutionCoefficient: resolutionHours,
|
|
|
SharedResourceInfo: sr,
|
|
|
}
|
|
|
- result := AggregateCostData(costData, field, subfields, a.Cloud, opts)
|
|
|
- a.AggregateCache.Set(aggKey, result, cache.DefaultExpiration)
|
|
|
+ result := AggregateCostData(costData, field, subfields, A.Cloud, opts)
|
|
|
+ A.AggregateCache.Set(aggKey, result, cache.DefaultExpiration)
|
|
|
|
|
|
w.Write(WrapDataWithMessage(result, nil, fmt.Sprintf("aggregate cache miss: %s", aggKey)))
|
|
|
}
|