github.com/go-graphite/carbonapi@v0.17.0/expr/functions/holtWintersAberration/function.go (about) 1 package holtWintersAberration 2 3 import ( 4 "context" 5 "math" 6 7 "github.com/go-graphite/carbonapi/expr/helper" 8 "github.com/go-graphite/carbonapi/expr/holtwinters" 9 "github.com/go-graphite/carbonapi/expr/interfaces" 10 "github.com/go-graphite/carbonapi/expr/types" 11 "github.com/go-graphite/carbonapi/pkg/parser" 12 pb "github.com/go-graphite/protocol/carbonapi_v3_pb" 13 ) 14 15 type holtWintersAberration struct{} 16 17 func GetOrder() interfaces.Order { 18 return interfaces.Any 19 } 20 21 func New(configFile string) []interfaces.FunctionMetadata { 22 res := make([]interfaces.FunctionMetadata, 0) 23 f := &holtWintersAberration{} 24 functions := []string{"holtWintersAberration"} 25 for _, n := range functions { 26 res = append(res, interfaces.FunctionMetadata{Name: n, F: f}) 27 } 28 return res 29 } 30 31 func (f *holtWintersAberration) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) { 32 bootstrapInterval, err := e.GetIntervalNamedOrPosArgDefault("bootstrapInterval", 2, 1, holtwinters.DefaultBootstrapInterval) 33 if err != nil { 34 return nil, err 35 } 36 37 args, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values) 38 if err != nil { 39 return nil, err 40 } 41 42 // Note: additional fetch requests are added with an adjusted start time in expr.Metrics() (in 43 // pkg/parser/parser.go) so that the appropriate data corresponding to the adjusted start time 44 // can be pre-fetched. 45 adjustedStartArgs, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from-bootstrapInterval, until, values) 46 if err != nil { 47 return nil, err 48 } 49 50 adjustedStartSeries := make(map[string]*types.MetricData) 51 for _, serie := range adjustedStartArgs { 52 adjustedStartSeries[serie.Name] = serie 53 } 54 55 delta, err := e.GetFloatNamedOrPosArgDefault("delta", 1, 3) 56 if err != nil { 57 return nil, err 58 } 59 60 seasonality, err := e.GetIntervalNamedOrPosArgDefault("seasonality", 3, 1, holtwinters.DefaultSeasonality) 61 if err != nil { 62 return nil, err 63 } 64 65 results := make([]*types.MetricData, 0, len(args)) 66 for _, arg := range args { 67 var ( 68 aberration []float64 69 ) 70 71 stepTime := arg.StepTime 72 73 if v, ok := adjustedStartSeries[arg.Name]; !ok || v == nil { 74 continue 75 } 76 77 lowerBand, upperBand := holtwinters.HoltWintersConfidenceBands(adjustedStartSeries[arg.Name].Values, stepTime, delta, bootstrapInterval, seasonality) 78 79 for i, v := range arg.Values { 80 if math.IsNaN(v) { 81 aberration = append(aberration, 0) 82 } else if !math.IsNaN(upperBand[i]) && v > upperBand[i] { 83 aberration = append(aberration, v-upperBand[i]) 84 } else if !math.IsNaN(lowerBand[i]) && v < lowerBand[i] { 85 aberration = append(aberration, v-lowerBand[i]) 86 } else { 87 aberration = append(aberration, 0) 88 } 89 } 90 91 name := "holtWintersAberration(" + arg.Name + ")" 92 r := types.MetricData{ 93 FetchResponse: pb.FetchResponse{ 94 Name: name, 95 Values: aberration, 96 StepTime: arg.StepTime, 97 StartTime: arg.StartTime, 98 StopTime: arg.StopTime, 99 PathExpression: name, 100 ConsolidationFunc: arg.ConsolidationFunc, 101 XFilesFactor: arg.XFilesFactor, 102 }, 103 Tags: helper.CopyTags(arg), 104 } 105 r.Tags["holtWintersAberration"] = "1" 106 results = append(results, &r) 107 } 108 return results, nil 109 } 110 111 // Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web 112 func (f *holtWintersAberration) Description() map[string]types.FunctionDescription { 113 return map[string]types.FunctionDescription{ 114 "holtWintersAberration": { 115 Description: "Performs a Holt-Winters forecast using the series as input data and plots the\npositive or negative deviation of the series data from the forecast.", 116 Function: "holtWintersAberration(seriesList, delta=3, bootstrapInterval='7d')", 117 Group: "Calculate", 118 Module: "graphite.render.functions", 119 Name: "holtWintersAberration", 120 Params: []types.FunctionParam{ 121 { 122 Name: "seriesList", 123 Required: true, 124 Type: types.SeriesList, 125 }, 126 { 127 Default: types.NewSuggestion(3), 128 Name: "delta", 129 Type: types.Integer, 130 }, 131 { 132 Default: types.NewSuggestion("7d"), 133 Name: "bootstrapInterval", 134 Suggestions: types.NewSuggestions( 135 "7d", 136 "30d", 137 ), 138 Type: types.Interval, 139 }, 140 }, 141 SeriesChange: true, // function aggregate metrics or change series items count 142 NameChange: true, // name changed 143 TagsChange: true, // name tag changed 144 ValuesChange: true, // values changed 145 }, 146 } 147 }