Skip to content

Commit

Permalink
add percentile debug and mae statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
Cloudzp committed Jun 4, 2024
1 parent 5f2c2b3 commit d71331f
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 4 deletions.
74 changes: 74 additions & 0 deletions pkg/prediction/percentile/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package percentile

import (
"fmt"
"time"

"k8s.io/klog/v2"

"github.com/gocrane/crane/pkg/common"
"github.com/gocrane/crane/pkg/metricnaming"
"github.com/gocrane/crane/pkg/prediction"
"github.com/gocrane/crane/pkg/prediction/config"
)

func Debug(predictor prediction.Interface, namer metricnaming.MetricNamer, config *config.Config) ([]*common.TimeSeries, []*common.TimeSeries, error) {
cfg, err := makeInternalConfig(config.Percentile, config.InitMode)
if err != nil {
return nil, nil, err
}

p := predictor.(*percentilePrediction)
historyTimeSeriesList, err := queryHistoryTimeSeries(p, namer, cfg)
if err != nil {
return nil, nil, err
}

queryExpr := namer.BuildUniqueKey()
klog.V(4).Infof("process analyzing metric namer: %v, config: %+v", namer.BuildUniqueKey(), *cfg)

signals := map[string]*aggregateSignal{}
if cfg.aggregated {
signal := newAggregateSignal(cfg)
for _, ts := range historyTimeSeriesList {
for _, s := range ts.Samples {
t := time.Unix(s.Timestamp, 0)
signal.addSample(t, s.Value)
}
}
signals[keyAll] = signal
} else {
for _, ts := range historyTimeSeriesList {
if len(ts.Samples) < 1 {
continue
}
key := prediction.AggregateSignalKey(ts.Labels)
signal := newAggregateSignal(cfg)
for _, s := range ts.Samples {
t := time.Unix(s.Timestamp, 0)
signal.addSample(t, s.Value)
}
signal.labels = ts.Labels
signals[key] = signal
}
}

return historyTimeSeriesList, p.getPredictedValuesFromSignals(queryExpr, signals, cfg), nil

}

func queryHistoryTimeSeries(predictor *percentilePrediction, namer metricnaming.MetricNamer, config *internalConfig) ([]*common.TimeSeries, error) {
p := predictor.GetHistoryProvider()
if p == nil {
return nil, fmt.Errorf("history provider not provisioned")
}

end := time.Now().Truncate(time.Minute)
start := end.Add(-config.historyLength)
historyTimeSeries, err := predictor.GetHistoryProvider().QueryTimeSeries(namer, start, end, config.sampleInterval)
if err != nil {
klog.ErrorS(err, "Failed to query history time series.")
return nil, err
}
return historyTimeSeries, nil
}
79 changes: 75 additions & 4 deletions pkg/server/handler/prediction/prediction.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import (

craneclientset "github.com/gocrane/api/pkg/generated/clientset/versioned"
"github.com/gocrane/api/prediction/v1alpha1"

"github.com/gocrane/crane/pkg/controller/timeseriesprediction"
"github.com/gocrane/crane/pkg/prediction/dsp"
"github.com/gocrane/crane/pkg/prediction/percentile"
predictormgr "github.com/gocrane/crane/pkg/predictor"
"github.com/gocrane/crane/pkg/server/config"
"github.com/gocrane/crane/pkg/server/ginwrapper"
Expand Down Expand Up @@ -107,9 +107,9 @@ func (dh *DebugHandler) Display(c *gin.Context) {
dspMAEThreeDays = mae(test.Samples[:threeDaySampleLength-1], estimate.Samples[:threeDaySampleLength-1])
}
dspMAEWeekly := 0.0
eightDaySampleLength := int(estimate.SampleRate * week.Seconds())
if len(estimate.Samples) >= eightDaySampleLength {
dspMAEWeekly = mae(test.Samples[:eightDaySampleLength-1], estimate.Samples[:eightDaySampleLength-1])
weeklyDaySampleLength := int(estimate.SampleRate * week.Seconds())
if len(estimate.Samples) >= weeklyDaySampleLength {
dspMAEWeekly = mae(test.Samples[:weeklyDaySampleLength-1], estimate.Samples[:weeklyDaySampleLength-1])
}
klog.Infof("dspMAE1d: %f,dspMAE3d: %f, dspMAE7d: %f", dspMAEDay, dspMAEThreeDays, dspMAEWeekly)
page := components.NewPage()
Expand All @@ -123,6 +123,67 @@ func (dh *DebugHandler) Display(c *gin.Context) {
klog.ErrorS(err, "Failed to display debug time series")
}

return
} else if tsp.Spec.PredictionMetrics[0].Algorithm.AlgorithmType == v1alpha1.AlgorithmTypePercentile && tsp.Spec.PredictionMetrics[0].Algorithm.Percentile != nil {
mc, err := timeseriesprediction.NewMetricContext(dh.selectorFetcher, tsp, dh.predictorManager)
if err != nil {
ginwrapper.WriteResponse(c, err, nil)
return
}

internalConf := mc.ConvertApiMetric2InternalConfig(&tsp.Spec.PredictionMetrics[0])
internalConf.Percentile.HistoryLength = "7d"
namer := mc.GetMetricNamer(&tsp.Spec.PredictionMetrics[0])
predictor := dh.predictorManager.GetPredictor(v1alpha1.AlgorithmTypePercentile)
history, estimate, err := percentile.Debug(predictor, namer, internalConf)
if err != nil {
ginwrapper.WriteResponse(c, err, nil)
return
}
if len(history) <= 0 || len(estimate) <= 0 {
c.Writer.WriteHeader(http.StatusBadRequest)
return
}

samples := history[0].Samples
estimateSamples := estimate[0].Samples
historySignal := &dsp.Signal{SampleRate: 1 / 60.0}
estimateSignal := &dsp.Signal{SampleRate: 1 / 60.0}
for _, v := range samples {
historySignal.Samples = append(historySignal.Samples, v.Value)
estimateSignal.Samples = append(estimateSignal.Samples, estimateSamples[0].Value)
}

predictMAEDay := 0.0
daySampleLength := int(estimateSignal.SampleRate * day.Seconds())
if len(estimateSignal.Samples) >= daySampleLength {
m := maxValue(historySignal.Samples[:daySampleLength-1])
predictMAEDay = mae([]float64{m}, []float64{estimateSamples[0].Value})
}
predictMAEThreeDays := 0.0
threeDaySampleLength := int(estimateSignal.SampleRate * threeDays.Seconds())
if len(estimateSignal.Samples) >= threeDaySampleLength {
m := maxValue(historySignal.Samples[:threeDaySampleLength-1])
predictMAEThreeDays = mae([]float64{m}, []float64{estimateSamples[0].Value})
}
predictMAEWeekly := 0.0
weeklySampleLength := int(estimateSignal.SampleRate * week.Seconds())
if len(estimateSignal.Samples) >= weeklySampleLength {
m := maxValue(historySignal.Samples[:weeklySampleLength-1])
predictMAEWeekly = mae([]float64{m}, []float64{estimateSamples[0].Value})
}

page := components.NewPage()
page.AddCharts(plots([]*dsp.Signal{historySignal, estimateSignal}, []string{"actual", "recommended"},
charts.WithTitleOpts(opts.Title{Title: "actual/recommended"})))

page.AddCharts(bar(predictMAEDay, predictMAEThreeDays, predictMAEWeekly))
err = page.Render(c.Writer)
if err != nil {
klog.ErrorS(err, "Failed to display debug time series")
}

c.Writer.WriteHeader(http.StatusBadRequest)
return
}
}
Expand All @@ -131,6 +192,16 @@ func (dh *DebugHandler) Display(c *gin.Context) {
return
}

func maxValue(testData []float64) float64 {
m := 0.0
for i := 0; i < len(testData); i++ {
if testData[i] > m {
m = testData[i]
}
}
return m
}

func mae(testData, estimateData []float64) float64 {
mae := 0.0
for i := 0; i < len(estimateData); i++ {
Expand Down

0 comments on commit d71331f

Please sign in to comment.