github.com/go-graphite/carbonapi@v0.17.0/expr/functions/aliasQuery/function.go (about) 1 package aliasQuery 2 3 import ( 4 "context" 5 "fmt" 6 "regexp" 7 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 ) 13 14 type aliasQuery struct{} 15 16 func GetOrder() interfaces.Order { 17 return interfaces.Any 18 } 19 20 func New(_ string) []interfaces.FunctionMetadata { 21 return []interfaces.FunctionMetadata{ 22 {Name: "aliasQuery", F: &aliasQuery{}}, 23 } 24 } 25 26 func (f *aliasQuery) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) { 27 seriesList, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values) 28 if err != nil { 29 return nil, err 30 } 31 search, err := e.GetStringArg(1) 32 if err != nil { 33 return nil, err 34 } 35 replace, err := e.GetStringArg(2) 36 if err != nil { 37 return nil, err 38 } 39 newName, err := e.GetStringArg(3) 40 if err != nil { 41 return nil, err 42 } 43 44 re, err := regexp.Compile(search) 45 if err != nil { 46 return nil, err 47 } 48 replace = helper.Backref.ReplaceAllString(replace, "$${$1}") 49 50 fetchTargets := make([]parser.Expr, len(seriesList)) 51 for i, series := range seriesList { 52 newTarget := re.ReplaceAllString(series.Name, replace) 53 expr, _, err := parser.ParseExpr(newTarget) 54 if err != nil { 55 return nil, err 56 } 57 fetchTargets[i] = expr 58 } 59 targetValues, err := eval.Fetch(ctx, fetchTargets, from, until, values) 60 if err != nil { 61 return nil, err 62 } 63 64 results := make([]*types.MetricData, len(seriesList)) 65 66 for i, series := range seriesList { 67 v, err := f.getLastValueOfSeries(ctx, eval, fetchTargets[i], from, until, targetValues) 68 if err != nil { 69 return nil, err 70 } 71 r := series.CopyLinkTags() 72 r.Name = fmt.Sprintf(newName, v) 73 results[i] = r 74 } 75 76 return results, nil 77 } 78 79 func (f *aliasQuery) getLastValueOfSeries(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, targetValues map[parser.MetricRequest][]*types.MetricData) (float64, error) { 80 res, err := helper.GetSeriesArg(ctx, eval, e, from, until, targetValues) 81 if err != nil { 82 return 0, err 83 } 84 85 if len(res) == 0 { 86 return 0, parser.ErrMissingTimeseries 87 } 88 89 if len(res[0].Values) == 0 { 90 return 0, parser.ErrMissingValues 91 } 92 93 return res[0].Values[len(res[0].Values)-1], nil 94 } 95 96 func (f *aliasQuery) Description() map[string]types.FunctionDescription { 97 return map[string]types.FunctionDescription{ 98 "aliasQuery": { 99 Description: "Performs a query to alias the metrics in seriesList.\nThe series in seriesList will be aliased by first translating the series names using the search & replace parameters, then using the last value of the resulting series to construct the alias using sprintf-style syntax.", 100 Function: "aliasQuery(seriesList, search, replace, newName)", 101 Group: "Alias", 102 Module: "graphite.render.functions", 103 Name: "aliasQuery", 104 Params: []types.FunctionParam{ 105 { 106 Name: "seriesList", 107 Required: true, 108 Type: types.SeriesList, 109 }, 110 { 111 Name: "search", 112 Required: true, 113 Type: types.String, 114 }, 115 { 116 Name: "replace", 117 Required: true, 118 Type: types.String, 119 }, 120 { 121 Name: "newName", 122 Required: true, 123 Type: types.String, 124 }, 125 }, 126 NameChange: true, 127 TagsChange: true, 128 }, 129 } 130 }