publish.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package metrics
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "net/http"
  6. "runtime"
  7. "strings"
  8. "time"
  9. "github.com/grafana/grafana/pkg/bus"
  10. "github.com/grafana/grafana/pkg/log"
  11. m "github.com/grafana/grafana/pkg/models"
  12. "github.com/grafana/grafana/pkg/plugins"
  13. "github.com/grafana/grafana/pkg/setting"
  14. )
  15. var metricsLogger log.Logger = log.New("metrics")
  16. var metricPublishCounter int64 = 0
  17. func Init() {
  18. settings := readSettings()
  19. initMetricVars(settings)
  20. go instrumentationLoop(settings)
  21. }
  22. func instrumentationLoop(settings *MetricSettings) chan struct{} {
  23. M_Instance_Start.Inc(1)
  24. onceEveryDayTick := time.NewTicker(time.Hour * 24)
  25. secondTicker := time.NewTicker(time.Second * time.Duration(settings.IntervalSeconds))
  26. for {
  27. select {
  28. case <-onceEveryDayTick.C:
  29. sendUsageStats()
  30. case <-secondTicker.C:
  31. if settings.Enabled {
  32. sendMetrics(settings)
  33. }
  34. }
  35. }
  36. }
  37. func sendMetrics(settings *MetricSettings) {
  38. if len(settings.Publishers) == 0 {
  39. return
  40. }
  41. updateTotalStats()
  42. metrics := MetricStats.GetSnapshots()
  43. for _, publisher := range settings.Publishers {
  44. publisher.Publish(metrics)
  45. }
  46. }
  47. func updateTotalStats() {
  48. // every interval also publish totals
  49. metricPublishCounter++
  50. if metricPublishCounter%10 == 0 {
  51. // get stats
  52. statsQuery := m.GetSystemStatsQuery{}
  53. if err := bus.Dispatch(&statsQuery); err != nil {
  54. metricsLogger.Error("Failed to get system stats", "error", err)
  55. return
  56. }
  57. M_StatTotal_Dashboards.Update(statsQuery.Result.Dashboards)
  58. M_StatTotal_Users.Update(statsQuery.Result.Users)
  59. M_StatTotal_Playlists.Update(statsQuery.Result.Playlists)
  60. M_StatTotal_Orgs.Update(statsQuery.Result.Orgs)
  61. }
  62. }
  63. func sendUsageStats() {
  64. if !setting.ReportingEnabled {
  65. return
  66. }
  67. metricsLogger.Debug("Sending anonymous usage stats to stats.grafana.org")
  68. version := strings.Replace(setting.BuildVersion, ".", "_", -1)
  69. metrics := map[string]interface{}{}
  70. report := map[string]interface{}{
  71. "version": version,
  72. "metrics": metrics,
  73. "os": runtime.GOOS,
  74. "arch": runtime.GOARCH,
  75. }
  76. statsQuery := m.GetSystemStatsQuery{}
  77. if err := bus.Dispatch(&statsQuery); err != nil {
  78. metricsLogger.Error("Failed to get system stats", "error", err)
  79. return
  80. }
  81. metrics["stats.dashboards.count"] = statsQuery.Result.Dashboards
  82. metrics["stats.users.count"] = statsQuery.Result.Users
  83. metrics["stats.orgs.count"] = statsQuery.Result.Orgs
  84. metrics["stats.playlist.count"] = statsQuery.Result.Playlists
  85. metrics["stats.plugins.apps.count"] = len(plugins.Apps)
  86. metrics["stats.plugins.panels.count"] = len(plugins.Panels)
  87. metrics["stats.plugins.datasources.count"] = len(plugins.DataSources)
  88. metrics["stats.alerts.count"] = statsQuery.Result.Alerts
  89. metrics["stats.active_users.count"] = statsQuery.Result.ActiveUsers
  90. metrics["stats.datasources.count"] = statsQuery.Result.Datasources
  91. dsStats := m.GetDataSourceStatsQuery{}
  92. if err := bus.Dispatch(&dsStats); err != nil {
  93. metricsLogger.Error("Failed to get datasource stats", "error", err)
  94. return
  95. }
  96. // send counters for each data source
  97. // but ignore any custom data sources
  98. // as sending that name could be sensitive information
  99. dsOtherCount := 0
  100. for _, dsStat := range dsStats.Result {
  101. if m.IsKnownDataSourcePlugin(dsStat.Type) {
  102. metrics["stats.ds."+dsStat.Type+".count"] = dsStat.Count
  103. } else {
  104. dsOtherCount += dsStat.Count
  105. }
  106. }
  107. metrics["stats.ds.other.count"] = dsOtherCount
  108. out, _ := json.MarshalIndent(report, "", " ")
  109. data := bytes.NewBuffer(out)
  110. client := http.Client{Timeout: time.Duration(5 * time.Second)}
  111. go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data)
  112. }