github.com/go-graphite/carbonapi@v0.17.0/expr/functions/heatMap/helpers.go (about) 1 package heatMap 2 3 import ( 4 "fmt" 5 "math" 6 "sort" 7 8 "github.com/go-graphite/carbonapi/expr/types" 9 ) 10 11 // Helper functions that are used to sort or validate metrics 12 func validateNeighbourSeries(series []*types.MetricData) error { 13 if len(series) == 0 { 14 return nil 15 } 16 s1 := series[0] 17 18 for i := 1; i < len(series); i++ { 19 s2 := series[i] 20 if s1.StartTime != s2.StartTime { 21 return fmt.Errorf("StartTime differs: %d!=%d", s1.StartTime, s2.StartTime) 22 } 23 if s1.StopTime != s2.StopTime { 24 return fmt.Errorf("StartTime differs: %d!=%d", s1.StopTime, s2.StopTime) 25 } 26 if s1.StepTime != s2.StepTime { 27 return fmt.Errorf("StartTime differs: %d!=%d", s1.StepTime, s2.StepTime) 28 } 29 if len(s1.Values) != len(s2.Values) { 30 return fmt.Errorf("values quantity differs: %d!=%d", len(s1.Values), len(s2.Values)) 31 } 32 } 33 return nil 34 } 35 36 // sortMetricData returns *types.MetricData list sorted by sum of the first values 37 func sortMetricData(list []*types.MetricData) []*types.MetricData { 38 // take 5 first not null values 39 const points = 5 40 41 // mate series with its weight (sum of first values) 42 type metricDataWeighted struct { 43 data *types.MetricData 44 weight float64 45 } 46 47 seriesQty := len(list) 48 if seriesQty < 2 { 49 return list 50 } 51 52 listWeighted := make([]metricDataWeighted, seriesQty) 53 for j := 0; j < seriesQty; j++ { 54 listWeighted[j].data = list[j] 55 } 56 57 pointsFound := 0 58 valuesQty := len(list[0].Values) 59 60 for i := 0; i < valuesQty && pointsFound < points; i++ { 61 // make sure that each series has current point not null 62 absent := false 63 for j := 0; j < seriesQty && !absent; j++ { 64 absent = math.IsNaN(list[j].Values[i]) 65 } 66 if absent { 67 continue 68 } 69 70 // accumulate sum of first not-null values 71 for j := 0; j < seriesQty; j++ { 72 listWeighted[j].weight += list[j].Values[i] 73 } 74 pointsFound++ 75 } 76 77 // sort series by its weight 78 if pointsFound > 0 { 79 sort.SliceStable(listWeighted, func(i, j int) bool { 80 return listWeighted[i].weight < listWeighted[j].weight 81 }) 82 for j := 0; j < seriesQty; j++ { 83 list[j] = listWeighted[j].data 84 } 85 } 86 87 return list 88 }