github.com/go-graphite/carbonapi@v0.17.0/expr/functions/mostDeviant/function.go (about) 1 package mostDeviant 2 3 import ( 4 "container/heap" 5 "context" 6 "math" 7 8 "github.com/go-graphite/carbonapi/expr/consolidations" 9 "github.com/go-graphite/carbonapi/expr/helper" 10 "github.com/go-graphite/carbonapi/expr/interfaces" 11 "github.com/go-graphite/carbonapi/expr/types" 12 "github.com/go-graphite/carbonapi/pkg/parser" 13 ) 14 15 type mostDeviant 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 := &mostDeviant{} 24 functions := []string{"mostDeviant"} 25 for _, n := range functions { 26 res = append(res, interfaces.FunctionMetadata{Name: n, F: f}) 27 } 28 return res 29 } 30 31 // mostDeviant(seriesList, n) -or- mostDeviant(n, seriesList) 32 func (f *mostDeviant) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) { 33 if e.ArgsLen() < 2 { 34 return nil, parser.ErrMissingArgument 35 } 36 37 var nArg int 38 if !e.Arg(0).IsConst() { 39 // mostDeviant(seriesList, n) 40 nArg = 1 41 } 42 seriesArg := nArg ^ 1 // XOR to make seriesArg the opposite argument. ( 0^1 -> 1 ; 1^1 -> 0 ) 43 44 n, err := e.GetIntArg(nArg) 45 if err != nil { 46 return nil, err 47 } 48 49 args, err := helper.GetSeriesArg(ctx, eval, e.Arg(seriesArg), from, until, values) 50 if err != nil { 51 return nil, err 52 } 53 54 mh := make(types.MetricHeap, 0, len(args)) 55 56 for index, arg := range args { 57 variance := consolidations.VarianceValue(arg.Values) 58 if math.IsNaN(variance) { 59 continue 60 } 61 62 if len(mh) < n { 63 heap.Push(&mh, types.MetricHeapElement{Idx: index, Val: variance}) 64 continue 65 } 66 67 if variance > mh[0].Val { 68 mh[0].Idx = index 69 mh[0].Val = variance 70 heap.Fix(&mh, 0) 71 } 72 } 73 74 results := make([]*types.MetricData, len(mh)) 75 76 for len(mh) > 0 { 77 v := heap.Pop(&mh).(types.MetricHeapElement) 78 results[len(mh)] = args[v.Idx] 79 } 80 81 return results, err 82 } 83 84 // Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web 85 func (f *mostDeviant) Description() map[string]types.FunctionDescription { 86 return map[string]types.FunctionDescription{ 87 "mostDeviant": { 88 Description: "Takes one metric or a wildcard seriesList followed by an integer N.\nDraws the N most deviant metrics.\nTo find the deviants, the standard deviation (sigma) of each series\nis taken and ranked. The top N standard deviations are returned.\n\n Example:\n\n.. code-block:: none\n\n &target=mostDeviant(server*.instance*.memory.free, 5)\n\nDraws the 5 instances furthest from the average memory free.", 89 Function: "mostDeviant(seriesList, n)", 90 Group: "Filter Series", 91 Module: "graphite.render.functions", 92 Name: "mostDeviant", 93 Params: []types.FunctionParam{ 94 { 95 Name: "seriesList", 96 Required: true, 97 Type: types.SeriesList, 98 }, 99 { 100 Name: "n", 101 Required: true, 102 Type: types.Integer, 103 }, 104 }, 105 SeriesChange: true, // function aggregate metrics or change series items count 106 }, 107 } 108 }