report_usage.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package metrics
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "net/http"
  6. "strings"
  7. "time"
  8. "github.com/grafana/grafana/pkg/bus"
  9. "github.com/grafana/grafana/pkg/log"
  10. "github.com/grafana/grafana/pkg/metrics/receiver"
  11. m "github.com/grafana/grafana/pkg/models"
  12. "github.com/grafana/grafana/pkg/plugins"
  13. "github.com/grafana/grafana/pkg/setting"
  14. )
  15. type MetricSender interface {
  16. Send(metrics map[string]interface{}) error
  17. }
  18. func StartUsageReportLoop() chan struct{} {
  19. M_Instance_Start.Inc(1)
  20. hourTicker := time.NewTicker(time.Hour * 24)
  21. secondTicker := time.NewTicker(time.Second * 10)
  22. sender := &receiver.GraphiteSender{
  23. Host: "localhost",
  24. Port: "2003",
  25. Protocol: "tcp",
  26. Prefix: "grafana.",
  27. }
  28. for {
  29. select {
  30. case <-hourTicker.C:
  31. sendUsageStats()
  32. case <-secondTicker.C:
  33. sendMetricUsage(sender)
  34. }
  35. }
  36. }
  37. func sendMetricUsage(sender MetricSender) {
  38. metrics := map[string]interface{}{}
  39. MetricStats.Each(func(name string, i interface{}) {
  40. switch metric := i.(type) {
  41. case Counter:
  42. if metric.Count() > 0 {
  43. metrics[name+".count"] = metric.Count()
  44. metric.Clear()
  45. }
  46. }
  47. })
  48. err := sender.Send(metrics)
  49. if err != nil {
  50. log.Error(1, "Failed to send metrics:", err)
  51. }
  52. }
  53. func sendUsageStats() {
  54. log.Trace("Sending anonymous usage stats to stats.grafana.org")
  55. version := strings.Replace(setting.BuildVersion, ".", "_", -1)
  56. metrics := map[string]interface{}{}
  57. report := map[string]interface{}{
  58. "version": version,
  59. "metrics": metrics,
  60. }
  61. UsageStats.Each(func(name string, i interface{}) {
  62. switch metric := i.(type) {
  63. case Counter:
  64. if metric.Count() > 0 {
  65. metrics[name+".count"] = metric.Count()
  66. metric.Clear()
  67. }
  68. }
  69. })
  70. statsQuery := m.GetSystemStatsQuery{}
  71. if err := bus.Dispatch(&statsQuery); err != nil {
  72. log.Error(3, "Failed to get system stats", err)
  73. return
  74. }
  75. metrics["stats.dashboards.count"] = statsQuery.Result.DashboardCount
  76. metrics["stats.users.count"] = statsQuery.Result.UserCount
  77. metrics["stats.orgs.count"] = statsQuery.Result.OrgCount
  78. metrics["stats.playlist.count"] = statsQuery.Result.PlaylistCount
  79. metrics["stats.plugins.apps.count"] = len(plugins.Apps)
  80. metrics["stats.plugins.panels.count"] = len(plugins.Panels)
  81. metrics["stats.plugins.datasources.count"] = len(plugins.DataSources)
  82. dsStats := m.GetDataSourceStatsQuery{}
  83. if err := bus.Dispatch(&dsStats); err != nil {
  84. log.Error(3, "Failed to get datasource stats", err)
  85. return
  86. }
  87. // send counters for each data source
  88. // but ignore any custom data sources
  89. // as sending that name could be sensitive information
  90. dsOtherCount := 0
  91. for _, dsStat := range dsStats.Result {
  92. if m.IsKnownDataSourcePlugin(dsStat.Type) {
  93. metrics["stats.ds."+dsStat.Type+".count"] = dsStat.Count
  94. } else {
  95. dsOtherCount += dsStat.Count
  96. }
  97. }
  98. metrics["stats.ds.other.count"] = dsOtherCount
  99. out, _ := json.MarshalIndent(report, "", " ")
  100. data := bytes.NewBuffer(out)
  101. client := http.Client{Timeout: time.Duration(5 * time.Second)}
  102. go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data)
  103. }