reducer.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package conditions
  2. import (
  3. "math"
  4. "sort"
  5. "github.com/grafana/grafana/pkg/tsdb"
  6. "gopkg.in/guregu/null.v3"
  7. )
  8. type QueryReducer interface {
  9. Reduce(timeSeries *tsdb.TimeSeries) null.Float
  10. }
  11. type SimpleReducer struct {
  12. Type string
  13. }
  14. func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) null.Float {
  15. if len(series.Points) == 0 {
  16. return null.FloatFromPtr(nil)
  17. }
  18. value := float64(0)
  19. allNull := true
  20. switch s.Type {
  21. case "avg":
  22. validPointsCount := 0
  23. for _, point := range series.Points {
  24. if point[0].Valid {
  25. value += point[0].Float64
  26. validPointsCount += 1
  27. allNull = false
  28. }
  29. }
  30. if validPointsCount > 0 {
  31. value = value / float64(validPointsCount)
  32. }
  33. case "sum":
  34. for _, point := range series.Points {
  35. if point[0].Valid {
  36. value += point[0].Float64
  37. allNull = false
  38. }
  39. }
  40. case "min":
  41. value = math.MaxFloat64
  42. for _, point := range series.Points {
  43. if point[0].Valid {
  44. allNull = false
  45. if value > point[0].Float64 {
  46. value = point[0].Float64
  47. }
  48. }
  49. }
  50. case "max":
  51. value = -math.MaxFloat64
  52. for _, point := range series.Points {
  53. if point[0].Valid {
  54. allNull = false
  55. if value < point[0].Float64 {
  56. value = point[0].Float64
  57. }
  58. }
  59. }
  60. case "count":
  61. value = float64(len(series.Points))
  62. allNull = false
  63. case "last":
  64. points := series.Points
  65. for i := len(points) - 1; i >= 0; i-- {
  66. if points[i][0].Valid {
  67. value = points[i][0].Float64
  68. allNull = false
  69. break
  70. }
  71. }
  72. case "median":
  73. var values []float64
  74. for _, v := range series.Points {
  75. if v[0].Valid {
  76. allNull = false
  77. values = append(values, v[0].Float64)
  78. }
  79. }
  80. if len(values) >= 1 {
  81. sort.Float64s(values)
  82. length := len(values)
  83. if length%2 == 1 {
  84. value = values[(length-1)/2]
  85. } else {
  86. value = (values[(length/2)-1] + values[length/2]) / 2
  87. }
  88. }
  89. }
  90. if allNull {
  91. return null.FloatFromPtr(nil)
  92. }
  93. return null.FloatFrom(value)
  94. }
  95. func NewSimpleReducer(typ string) *SimpleReducer {
  96. return &SimpleReducer{Type: typ}
  97. }