github.com/go-graphite/carbonapi@v0.17.0/expr/functions/smartSummarize/function.go (about) 1 package smartSummarize 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/go-graphite/carbonapi/expr/consolidations" 8 "github.com/go-graphite/carbonapi/expr/helper" 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 smartSummarize 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 := &smartSummarize{} 24 functions := []string{"smartSummarize"} 25 for _, n := range functions { 26 res = append(res, interfaces.FunctionMetadata{Name: n, F: f}) 27 } 28 return res 29 } 30 31 // smartSummarize(seriesList, intervalString, func='sum', alignTo=None) 32 func (f *smartSummarize) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) { 33 // TODO(dgryski): make sure the arrays are all the same 'size' 34 if e.ArgsLen() < 2 { 35 return nil, parser.ErrMissingArgument 36 } 37 38 alignToInterval, err := e.GetStringNamedOrPosArgDefault("alignTo", 3, "") 39 if err != nil { 40 return nil, err 41 } 42 43 if alignToInterval != "" { 44 // Note: the start time for the fetch request is adjusted in expr.Metrics() so that the fetched 45 // data is already aligned by interval if this parameter specifics an interval to align to 46 newStart, err := parser.StartAlignTo(from, alignToInterval) 47 if err != nil { 48 return nil, err 49 } 50 from = newStart 51 } 52 args, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values) 53 if err != nil { 54 return nil, err 55 } 56 57 if len(args) == 0 { 58 return []*types.MetricData{}, nil 59 } 60 61 bucketSizeInt32, err := e.GetIntervalArg(1, 1) 62 if err != nil { 63 return nil, err 64 } 65 if bucketSizeInt32 <= 0 { 66 return nil, parser.ErrInvalidInterval 67 } 68 bucketSize := int64(bucketSizeInt32) 69 bucketSizeStr := e.Arg(1).StringValue() 70 71 summarizeFunction, err := e.GetStringNamedOrPosArgDefault("func", 2, "sum") 72 if err != nil { 73 return nil, err 74 } 75 if err := consolidations.CheckValidConsolidationFunc(summarizeFunction); err != nil { 76 return nil, err 77 } 78 79 results := make([]*types.MetricData, len(args)) 80 for n, arg := range args { 81 var name string 82 83 if alignToInterval != "" { 84 name = "smartSummarize(" + arg.Name + ",'" + bucketSizeStr + "','" + summarizeFunction + "','" + alignToInterval + "')" 85 } else { 86 name = "smartSummarize(" + arg.Name + ",'" + bucketSizeStr + "','" + summarizeFunction + "')" 87 } 88 89 r := types.MetricData{ 90 FetchResponse: pb.FetchResponse{ 91 Name: name, 92 StepTime: bucketSize, 93 StartTime: arg.StartTime, 94 StopTime: arg.StopTime, 95 ConsolidationFunc: arg.ConsolidationFunc, 96 }, 97 Tags: helper.CopyTags(arg), 98 } 99 r.Tags["smartSummarize"] = fmt.Sprintf("%d", bucketSizeInt32) 100 r.Tags["smartSummarizeFunction"] = summarizeFunction 101 102 ts := arg.StartTime 103 for ts < arg.StopTime { 104 bucketUpperBound := ts + bucketSize 105 bucketStart := (ts - arg.StartTime + arg.StepTime - 1) / arg.StepTime // equivalent to ceil((ts-arg.StartTime) / arg.StepTime) 106 bucketEnd := (bucketUpperBound - arg.StartTime + arg.StepTime - 1) / arg.StepTime // equivalent to ceil((until-arg.StartTime) / arg.StepTime) 107 108 if bucketEnd > int64(len(arg.Values)) { 109 bucketEnd = int64(len(arg.Values)) 110 } 111 112 rv := consolidations.SummarizeValues(summarizeFunction, arg.Values[bucketStart:bucketEnd], arg.XFilesFactor) 113 r.Values = append(r.Values, rv) 114 ts = bucketUpperBound 115 } 116 r.StopTime = ts 117 results[n] = &r 118 } 119 return results, nil 120 } 121 122 // Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web 123 func (f *smartSummarize) Description() map[string]types.FunctionDescription { 124 return map[string]types.FunctionDescription{ 125 "smartSummarize": { 126 Description: "Smarter version of summarize.\nThe alignToFrom boolean parameter has been replaced by alignTo and no longer has any effect. Alignment can be to years, months, weeks, days, hours, and minutes.\nThis function can be used with aggregation functions average, median, sum, min, max, diff, stddev, count, range, multiply & last.", 127 Function: "smartSummarize(seriesList, intervalString, func='sum', alignTo=None)", 128 Group: "Transform", 129 Module: "graphite.render.functions", 130 Name: "smartSummarize", 131 Params: []types.FunctionParam{ 132 { 133 Name: "seriesList", 134 Required: true, 135 Type: types.SeriesList, 136 }, 137 { 138 Name: "intervalString", 139 Required: true, 140 Suggestions: types.NewSuggestions( 141 "10min", 142 "1h", 143 "1d", 144 ), 145 Type: types.Interval, 146 }, 147 { 148 Default: types.NewSuggestion("sum"), 149 Name: "func", 150 Options: types.StringsToSuggestionList(consolidations.AvailableSummarizers), 151 Type: types.AggFunc, 152 }, 153 { 154 Name: "alignTo", 155 Suggestions: types.NewSuggestions( 156 "1m", 157 "1d", 158 "1y", 159 ), 160 Type: types.Interval, 161 }, 162 }, 163 NameChange: true, // name changed 164 ValuesChange: true, // values changed 165 }, 166 } 167 }