reducer.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package conditions
  2. import (
  3. "math"
  4. "sort"
  5. "github.com/grafana/grafana/pkg/components/null"
  6. "github.com/grafana/grafana/pkg/tsdb"
  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. case "diff":
  90. var (
  91. points = series.Points
  92. first float64
  93. i int
  94. )
  95. // get the newest point
  96. for i = len(points) - 1; i >= 0; i-- {
  97. if points[i][0].Valid {
  98. allNull = false
  99. first = points[i][0].Float64
  100. break
  101. }
  102. }
  103. // get other points
  104. points = points[0:i]
  105. for i := len(points) - 1; i >= 0; i-- {
  106. if points[i][0].Valid {
  107. allNull = false
  108. value = first - points[i][0].Float64
  109. break
  110. }
  111. }
  112. case "percent_diff":
  113. var (
  114. points = series.Points
  115. first float64
  116. i int
  117. )
  118. // get the newest point
  119. for i = len(points) - 1; i >= 0; i-- {
  120. if points[i][0].Valid {
  121. allNull = false
  122. first = points[i][0].Float64
  123. break
  124. }
  125. }
  126. // get other points
  127. points = points[0:i]
  128. for i := len(points) - 1; i >= 0; i-- {
  129. if points[i][0].Valid {
  130. allNull = false
  131. val := (first - points[i][0].Float64) / points[i][0].Float64 * 100
  132. value = math.Abs(val)
  133. break
  134. }
  135. }
  136. case "count_non_null":
  137. for _, v := range series.Points {
  138. if v[0].Valid {
  139. value++
  140. }
  141. }
  142. if value > 0 {
  143. allNull = false
  144. }
  145. }
  146. if allNull {
  147. return null.FloatFromPtr(nil)
  148. }
  149. return null.FloatFrom(value)
  150. }
  151. func NewSimpleReducer(typ string) *SimpleReducer {
  152. return &SimpleReducer{Type: typ}
  153. }