metrics_test.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package metrics
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "runtime"
  6. "sync"
  7. "testing"
  8. "time"
  9. "net/http"
  10. "net/http/httptest"
  11. "github.com/grafana/grafana/pkg/bus"
  12. "github.com/grafana/grafana/pkg/components/simplejson"
  13. "github.com/grafana/grafana/pkg/models"
  14. "github.com/grafana/grafana/pkg/plugins"
  15. "github.com/grafana/grafana/pkg/setting"
  16. . "github.com/smartystreets/goconvey/convey"
  17. )
  18. func TestMetrics(t *testing.T) {
  19. Convey("Test send usage stats", t, func() {
  20. var getSystemStatsQuery *models.GetSystemStatsQuery
  21. bus.AddHandler("test", func(query *models.GetSystemStatsQuery) error {
  22. query.Result = &models.SystemStats{
  23. Dashboards: 1,
  24. Datasources: 2,
  25. Users: 3,
  26. ActiveUsers: 4,
  27. Orgs: 5,
  28. Playlists: 6,
  29. Alerts: 7,
  30. Stars: 8,
  31. Folders: 9,
  32. DashboardPermissions: 10,
  33. FolderPermissions: 11,
  34. ProvisionedDashboards: 12,
  35. Snapshots: 13,
  36. Teams: 14,
  37. }
  38. getSystemStatsQuery = query
  39. return nil
  40. })
  41. var getDataSourceStatsQuery *models.GetDataSourceStatsQuery
  42. bus.AddHandler("test", func(query *models.GetDataSourceStatsQuery) error {
  43. query.Result = []*models.DataSourceStats{
  44. {
  45. Type: models.DS_ES,
  46. Count: 9,
  47. },
  48. {
  49. Type: models.DS_PROMETHEUS,
  50. Count: 10,
  51. },
  52. {
  53. Type: "unknown_ds",
  54. Count: 11,
  55. },
  56. {
  57. Type: "unknown_ds2",
  58. Count: 12,
  59. },
  60. }
  61. getDataSourceStatsQuery = query
  62. return nil
  63. })
  64. var getDataSourceAccessStatsQuery *models.GetDataSourceAccessStatsQuery
  65. bus.AddHandler("test", func(query *models.GetDataSourceAccessStatsQuery) error {
  66. query.Result = []*models.DataSourceAccessStats{
  67. {
  68. Type: models.DS_ES,
  69. Access: "direct",
  70. Count: 1,
  71. },
  72. {
  73. Type: models.DS_ES,
  74. Access: "proxy",
  75. Count: 2,
  76. },
  77. {
  78. Type: models.DS_PROMETHEUS,
  79. Access: "proxy",
  80. Count: 3,
  81. },
  82. {
  83. Type: "unknown_ds",
  84. Access: "proxy",
  85. Count: 4,
  86. },
  87. {
  88. Type: "unknown_ds2",
  89. Access: "",
  90. Count: 5,
  91. },
  92. {
  93. Type: "unknown_ds3",
  94. Access: "direct",
  95. Count: 6,
  96. },
  97. {
  98. Type: "unknown_ds4",
  99. Access: "direct",
  100. Count: 7,
  101. },
  102. {
  103. Type: "unknown_ds5",
  104. Access: "proxy",
  105. Count: 8,
  106. },
  107. }
  108. getDataSourceAccessStatsQuery = query
  109. return nil
  110. })
  111. var wg sync.WaitGroup
  112. var responseBuffer *bytes.Buffer
  113. var req *http.Request
  114. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  115. req = r
  116. buf, err := ioutil.ReadAll(r.Body)
  117. if err != nil {
  118. t.Fatalf("Failed to read response body, err=%v", err)
  119. }
  120. responseBuffer = bytes.NewBuffer(buf)
  121. wg.Done()
  122. }))
  123. usageStatsURL = ts.URL
  124. sendUsageStats()
  125. Convey("Given reporting not enabled and sending usage stats", func() {
  126. setting.ReportingEnabled = false
  127. sendUsageStats()
  128. Convey("Should not gather stats or call http endpoint", func() {
  129. So(getSystemStatsQuery, ShouldBeNil)
  130. So(getDataSourceStatsQuery, ShouldBeNil)
  131. So(getDataSourceAccessStatsQuery, ShouldBeNil)
  132. So(req, ShouldBeNil)
  133. })
  134. })
  135. Convey("Given reporting enabled and sending usage stats", func() {
  136. setting.ReportingEnabled = true
  137. setting.BuildVersion = "5.0.0"
  138. wg.Add(1)
  139. sendUsageStats()
  140. Convey("Should gather stats and call http endpoint", func() {
  141. if waitTimeout(&wg, 2*time.Second) {
  142. t.Fatalf("Timed out waiting for http request")
  143. }
  144. So(getSystemStatsQuery, ShouldNotBeNil)
  145. So(getDataSourceStatsQuery, ShouldNotBeNil)
  146. So(getDataSourceAccessStatsQuery, ShouldNotBeNil)
  147. So(req, ShouldNotBeNil)
  148. So(req.Method, ShouldEqual, http.MethodPost)
  149. So(req.Header.Get("Content-Type"), ShouldEqual, "application/json")
  150. So(responseBuffer, ShouldNotBeNil)
  151. j, err := simplejson.NewFromReader(responseBuffer)
  152. So(err, ShouldBeNil)
  153. So(j.Get("version").MustString(), ShouldEqual, "5_0_0")
  154. So(j.Get("os").MustString(), ShouldEqual, runtime.GOOS)
  155. So(j.Get("arch").MustString(), ShouldEqual, runtime.GOARCH)
  156. metrics := j.Get("metrics")
  157. So(metrics.Get("stats.dashboards.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Dashboards)
  158. So(metrics.Get("stats.users.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Users)
  159. So(metrics.Get("stats.orgs.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Orgs)
  160. So(metrics.Get("stats.playlist.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Playlists)
  161. So(metrics.Get("stats.plugins.apps.count").MustInt(), ShouldEqual, len(plugins.Apps))
  162. So(metrics.Get("stats.plugins.panels.count").MustInt(), ShouldEqual, len(plugins.Panels))
  163. So(metrics.Get("stats.plugins.datasources.count").MustInt(), ShouldEqual, len(plugins.DataSources))
  164. So(metrics.Get("stats.alerts.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Alerts)
  165. So(metrics.Get("stats.active_users.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.ActiveUsers)
  166. So(metrics.Get("stats.datasources.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Datasources)
  167. So(metrics.Get("stats.stars.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Stars)
  168. So(metrics.Get("stats.folders.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Folders)
  169. So(metrics.Get("stats.dashboard_permissions.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.DashboardPermissions)
  170. So(metrics.Get("stats.folder_permissions.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.FolderPermissions)
  171. So(metrics.Get("stats.provisioned_dashboards.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.ProvisionedDashboards)
  172. So(metrics.Get("stats.snapshots.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Snapshots)
  173. So(metrics.Get("stats.teams.count").MustInt(), ShouldEqual, getSystemStatsQuery.Result.Teams)
  174. So(metrics.Get("stats.ds."+models.DS_ES+".count").MustInt(), ShouldEqual, 9)
  175. So(metrics.Get("stats.ds."+models.DS_PROMETHEUS+".count").MustInt(), ShouldEqual, 10)
  176. So(metrics.Get("stats.ds.other.count").MustInt(), ShouldEqual, 11+12)
  177. So(metrics.Get("stats.ds_access."+models.DS_ES+".direct.count").MustInt(), ShouldEqual, 1)
  178. So(metrics.Get("stats.ds_access."+models.DS_ES+".proxy.count").MustInt(), ShouldEqual, 2)
  179. So(metrics.Get("stats.ds_access."+models.DS_PROMETHEUS+".proxy.count").MustInt(), ShouldEqual, 3)
  180. So(metrics.Get("stats.ds_access.other.direct.count").MustInt(), ShouldEqual, 6+7)
  181. So(metrics.Get("stats.ds_access.other.proxy.count").MustInt(), ShouldEqual, 4+8)
  182. })
  183. })
  184. Reset(func() {
  185. ts.Close()
  186. })
  187. })
  188. }
  189. func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
  190. c := make(chan struct{})
  191. go func() {
  192. defer close(c)
  193. wg.Wait()
  194. }()
  195. select {
  196. case <-c:
  197. return false // completed normally
  198. case <-time.After(timeout):
  199. return true // timed out
  200. }
  201. }