github.com/go-graphite/carbonapi@v0.17.0/expr/functions/heatMap/function.go (about) 1 package heatMap 2 3 import ( 4 "context" 5 "math" 6 7 pb "github.com/go-graphite/protocol/carbonapi_v3_pb" 8 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 heatMap struct{} 16 17 func GetOrder() interfaces.Order { 18 return interfaces.Any 19 } 20 21 func New(_ string) []interfaces.FunctionMetadata { 22 return []interfaces.FunctionMetadata{{ 23 F: &heatMap{}, 24 Name: "heatMap", 25 }} 26 } 27 28 func (f *heatMap) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) { 29 series, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values) 30 if err != nil { 31 return nil, err 32 } 33 34 series = sortMetricData(series) 35 seriesQty := len(series) 36 result := make([]*types.MetricData, 0, seriesQty-1) 37 38 if err = validateNeighbourSeries(series); err != nil { 39 return nil, err 40 } 41 for i := 1; i < seriesQty; i++ { 42 curr, prev := series[i], series[i-1] 43 44 pointsQty := len(curr.Values) 45 r := &types.MetricData{ 46 FetchResponse: pb.FetchResponse{ 47 Name: "heatMap(" + curr.Name + "," + prev.Name + ")", 48 Values: make([]float64, pointsQty), 49 StartTime: curr.StartTime, 50 StopTime: curr.StopTime, 51 StepTime: curr.StepTime, 52 }, 53 Tags: curr.Tags, 54 } 55 56 for j := 0; j < pointsQty; j++ { 57 if math.IsNaN(curr.Values[j]) || math.IsNaN(prev.Values[j]) { 58 r.Values[j] = math.NaN() 59 continue 60 } 61 r.Values[j] = curr.Values[j] - prev.Values[j] 62 } 63 64 result = append(result, r) 65 } 66 67 return result, nil 68 } 69 70 const description = `Compute heat-map like result based on a values of a metric. 71 72 All metrics are assigned weights, based on the sum of their first 5 values and then sorted based on that. 73 74 After that for the sorted metrics, diff with the previous one will be computed. 75 76 Assuming seriesList has values N series in total (sorted by sum of the first 5 values): 77 (a[1], a[2], ..., a[N]). Then heatMap will output N-1 series: (a[2] - a[1], a[3] - a[2], ..., a[N] - a[N-1]). 78 79 That function produce similar result to prometheus heatmaps for any list of incrementing counters and plays well with 80 grafana heatmap graph type.' 81 ` 82 83 func (f *heatMap) Description() map[string]types.FunctionDescription { 84 return map[string]types.FunctionDescription{ 85 "heatMap": { 86 Description: description, 87 Function: "heatMap(seriesList)", 88 Group: "Transform", 89 Module: "graphite.render.functions", 90 Name: "heatMap", 91 Params: []types.FunctionParam{ 92 { 93 Name: "seriesList", 94 Required: true, 95 Type: types.SeriesList, 96 }, 97 }, 98 SeriesChange: true, // function aggregate metrics or change series items count 99 NameChange: true, // name changed 100 ValuesChange: true, // values changed 101 }, 102 } 103 }