scenarios.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. package testdata
  2. import (
  3. "encoding/json"
  4. "math/rand"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "github.com/grafana/grafana/pkg/components/null"
  9. "github.com/grafana/grafana/pkg/log"
  10. "github.com/grafana/grafana/pkg/tsdb"
  11. )
  12. type ScenarioHandler func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult
  13. type Scenario struct {
  14. Id string `json:"id"`
  15. Name string `json:"name"`
  16. StringInput string `json:"stringOption"`
  17. Description string `json:"description"`
  18. Handler ScenarioHandler `json:"-"`
  19. }
  20. var ScenarioRegistry map[string]*Scenario
  21. func init() {
  22. ScenarioRegistry = make(map[string]*Scenario)
  23. logger := log.New("tsdb.testdata")
  24. logger.Debug("Initializing TestData Scenario")
  25. registerScenario(&Scenario{
  26. Id: "exponential_heatmap_bucket_data",
  27. Name: "Exponential heatmap bucket data",
  28. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  29. to := context.TimeRange.GetToAsMsEpoch()
  30. var series []*tsdb.TimeSeries
  31. start := 1
  32. factor := 2
  33. for i := 0; i < 10; i++ {
  34. timeWalkerMs := context.TimeRange.GetFromAsMsEpoch()
  35. serie := &tsdb.TimeSeries{Name: strconv.Itoa(start)}
  36. start *= factor
  37. points := make(tsdb.TimeSeriesPoints, 0)
  38. for j := int64(0); j < 100 && timeWalkerMs < to; j++ {
  39. v := float64(rand.Int63n(100))
  40. points = append(points, tsdb.NewTimePoint(null.FloatFrom(v), float64(timeWalkerMs)))
  41. timeWalkerMs += query.IntervalMs * 50
  42. }
  43. serie.Points = points
  44. series = append(series, serie)
  45. }
  46. queryRes := tsdb.NewQueryResult()
  47. queryRes.Series = append(queryRes.Series, series...)
  48. return queryRes
  49. },
  50. })
  51. registerScenario(&Scenario{
  52. Id: "linear_heatmap_bucket_data",
  53. Name: "Linear heatmap bucket data",
  54. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  55. to := context.TimeRange.GetToAsMsEpoch()
  56. var series []*tsdb.TimeSeries
  57. for i := 0; i < 10; i++ {
  58. timeWalkerMs := context.TimeRange.GetFromAsMsEpoch()
  59. serie := &tsdb.TimeSeries{Name: strconv.Itoa(i * 10)}
  60. points := make(tsdb.TimeSeriesPoints, 0)
  61. for j := int64(0); j < 100 && timeWalkerMs < to; j++ {
  62. v := float64(rand.Int63n(100))
  63. points = append(points, tsdb.NewTimePoint(null.FloatFrom(v), float64(timeWalkerMs)))
  64. timeWalkerMs += query.IntervalMs * 50
  65. }
  66. serie.Points = points
  67. series = append(series, serie)
  68. }
  69. queryRes := tsdb.NewQueryResult()
  70. queryRes.Series = append(queryRes.Series, series...)
  71. return queryRes
  72. },
  73. })
  74. registerScenario(&Scenario{
  75. Id: "random_walk",
  76. Name: "Random Walk",
  77. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  78. return getRandomWalk(query, context)
  79. },
  80. })
  81. registerScenario(&Scenario{
  82. Id: "slow_query",
  83. Name: "Slow Query",
  84. StringInput: "5s",
  85. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  86. stringInput := query.Model.Get("stringInput").MustString()
  87. parsedInterval, _ := time.ParseDuration(stringInput)
  88. time.Sleep(parsedInterval)
  89. return getRandomWalk(query, context)
  90. },
  91. })
  92. registerScenario(&Scenario{
  93. Id: "no_data_points",
  94. Name: "No Data Points",
  95. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  96. return tsdb.NewQueryResult()
  97. },
  98. })
  99. registerScenario(&Scenario{
  100. Id: "datapoints_outside_range",
  101. Name: "Datapoints Outside Range",
  102. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  103. queryRes := tsdb.NewQueryResult()
  104. series := newSeriesForQuery(query)
  105. outsideTime := context.TimeRange.MustGetFrom().Add(-1*time.Hour).Unix() * 1000
  106. series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(10), float64(outsideTime)))
  107. queryRes.Series = append(queryRes.Series, series)
  108. return queryRes
  109. },
  110. })
  111. registerScenario(&Scenario{
  112. Id: "manual_entry",
  113. Name: "Manual Entry",
  114. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  115. queryRes := tsdb.NewQueryResult()
  116. points := query.Model.Get("points").MustArray()
  117. series := newSeriesForQuery(query)
  118. startTime := context.TimeRange.GetFromAsMsEpoch()
  119. endTime := context.TimeRange.GetToAsMsEpoch()
  120. for _, val := range points {
  121. pointValues := val.([]interface{})
  122. var value null.Float
  123. var time int64
  124. if valueFloat, err := strconv.ParseFloat(string(pointValues[0].(json.Number)), 64); err == nil {
  125. value = null.FloatFrom(valueFloat)
  126. }
  127. if timeInt, err := strconv.ParseInt(string(pointValues[1].(json.Number)), 10, 64); err != nil {
  128. continue
  129. } else {
  130. time = timeInt
  131. }
  132. if time >= startTime && time <= endTime {
  133. series.Points = append(series.Points, tsdb.NewTimePoint(value, float64(time)))
  134. }
  135. }
  136. queryRes.Series = append(queryRes.Series, series)
  137. return queryRes
  138. },
  139. })
  140. registerScenario(&Scenario{
  141. Id: "csv_metric_values",
  142. Name: "CSV Metric Values",
  143. StringInput: "1,20,90,30,5,0",
  144. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  145. queryRes := tsdb.NewQueryResult()
  146. stringInput := query.Model.Get("stringInput").MustString()
  147. stringInput = strings.Replace(stringInput, " ", "", -1)
  148. values := []null.Float{}
  149. for _, strVal := range strings.Split(stringInput, ",") {
  150. if strVal == "null" {
  151. values = append(values, null.FloatFromPtr(nil))
  152. }
  153. if val, err := strconv.ParseFloat(strVal, 64); err == nil {
  154. values = append(values, null.FloatFrom(val))
  155. }
  156. }
  157. if len(values) == 0 {
  158. return queryRes
  159. }
  160. series := newSeriesForQuery(query)
  161. startTime := context.TimeRange.GetFromAsMsEpoch()
  162. endTime := context.TimeRange.GetToAsMsEpoch()
  163. step := (endTime - startTime) / int64(len(values)-1)
  164. for _, val := range values {
  165. series.Points = append(series.Points, tsdb.TimePoint{val, null.FloatFrom(float64(startTime))})
  166. startTime += step
  167. }
  168. queryRes.Series = append(queryRes.Series, series)
  169. return queryRes
  170. },
  171. })
  172. registerScenario(&Scenario{
  173. Id: "table_static",
  174. Name: "Table Static",
  175. Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
  176. timeWalkerMs := context.TimeRange.GetFromAsMsEpoch()
  177. to := context.TimeRange.GetToAsMsEpoch()
  178. table := tsdb.Table{
  179. Columns: []tsdb.TableColumn{
  180. {Text: "Time"},
  181. {Text: "Message"},
  182. {Text: "Description"},
  183. {Text: "Value"},
  184. },
  185. Rows: []tsdb.RowValues{},
  186. }
  187. for i := int64(0); i < 10 && timeWalkerMs < to; i++ {
  188. table.Rows = append(table.Rows, tsdb.RowValues{float64(timeWalkerMs), "This is a message", "Description", 23.1})
  189. timeWalkerMs += query.IntervalMs
  190. }
  191. queryRes := tsdb.NewQueryResult()
  192. queryRes.Tables = append(queryRes.Tables, &table)
  193. return queryRes
  194. },
  195. })
  196. }
  197. func getRandomWalk(query *tsdb.Query, tsdbQuery *tsdb.TsdbQuery) *tsdb.QueryResult {
  198. timeWalkerMs := tsdbQuery.TimeRange.GetFromAsMsEpoch()
  199. to := tsdbQuery.TimeRange.GetToAsMsEpoch()
  200. series := newSeriesForQuery(query)
  201. points := make(tsdb.TimeSeriesPoints, 0)
  202. walker := rand.Float64() * 100
  203. for i := int64(0); i < 10000 && timeWalkerMs < to; i++ {
  204. points = append(points, tsdb.NewTimePoint(null.FloatFrom(walker), float64(timeWalkerMs)))
  205. walker += rand.Float64() - 0.5
  206. timeWalkerMs += query.IntervalMs
  207. }
  208. series.Points = points
  209. queryRes := tsdb.NewQueryResult()
  210. queryRes.Series = append(queryRes.Series, series)
  211. return queryRes
  212. }
  213. func registerScenario(scenario *Scenario) {
  214. ScenarioRegistry[scenario.Id] = scenario
  215. }
  216. func newSeriesForQuery(query *tsdb.Query) *tsdb.TimeSeries {
  217. alias := query.Model.Get("alias").MustString("")
  218. if alias == "" {
  219. alias = query.RefId + "-series"
  220. }
  221. return &tsdb.TimeSeries{Name: alias}
  222. }