telemetry.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. package serverctl
  2. import (
  3. "encoding/json"
  4. "time"
  5. "github.com/gravitl/netmaker/database"
  6. "github.com/gravitl/netmaker/logger"
  7. "github.com/gravitl/netmaker/logic"
  8. "github.com/gravitl/netmaker/models"
  9. "github.com/gravitl/netmaker/servercfg"
  10. "github.com/posthog/posthog-go"
  11. )
  12. // POSTHOG_PUB_KEY - Key for sending data to PostHog
  13. const POSTHOG_PUB_KEY = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES"
  14. // POSTHOG_ENDPOINT - Endpoint of PostHog server
  15. const POSTHOG_ENDPOINT = "https://app.posthog.com"
  16. // TELEMETRY_HOURS_BETWEEN_SEND - How long to wait before sending telemetry to server (24 hours)
  17. const TELEMETRY_HOURS_BETWEEN_SEND = 24
  18. // TelemetryCheckpoint - Checks if 24 hours has passed since telemetry was last sent. If so, sends telemetry data to posthog
  19. func TelemetryCheckpoint() error {
  20. // if telemetry is turned off, return without doing anything
  21. if servercfg.Telemetry() == "off" {
  22. return nil
  23. }
  24. // get the telemetry record in the DB, which contains a timestamp
  25. telRecord, err := fetchTelemetryRecord()
  26. if err != nil {
  27. return err
  28. }
  29. sendtime := time.Unix(telRecord.LastSend, 0).Add(time.Hour * time.Duration(TELEMETRY_HOURS_BETWEEN_SEND))
  30. // can set to 2 minutes for testing
  31. //sendtime := time.Unix(telRecord.LastSend, 0).Add(time.Minute * 2)
  32. enoughTimeElapsed := time.Now().After(sendtime)
  33. // if more than 24 hours has elapsed, send telemetry to posthog
  34. if enoughTimeElapsed {
  35. err = sendTelemetry(telRecord.UUID)
  36. if err != nil {
  37. logger.Log(1, err.Error())
  38. }
  39. }
  40. return nil
  41. }
  42. // sendTelemetry - gathers telemetry data and sends to posthog
  43. func sendTelemetry(serverUUID string) error {
  44. // get telemetry data
  45. d, err := fetchTelemetryData()
  46. if err != nil {
  47. return err
  48. }
  49. client, err := posthog.NewWithConfig(POSTHOG_PUB_KEY, posthog.Config{Endpoint: POSTHOG_ENDPOINT})
  50. if err != nil {
  51. return err
  52. }
  53. defer client.Close()
  54. // send to posthog
  55. err = client.Enqueue(posthog.Capture{
  56. DistinctId: serverUUID,
  57. Event: "daily checkin",
  58. Properties: posthog.NewProperties().
  59. Set("nodes", d.Nodes).
  60. Set("non-server nodes", d.Count.NonServer).
  61. Set("extclients", d.ExtClients).
  62. Set("users", d.Users).
  63. Set("networks", d.Networks).
  64. Set("linux", d.Count.Linux).
  65. Set("darwin", d.Count.MacOS).
  66. Set("windows", d.Count.Windows).
  67. Set("freebsd", d.Count.FreeBSD).
  68. Set("docker", d.Count.Docker).
  69. Set("k8s", d.Count.K8S).
  70. Set("version", d.Version),
  71. })
  72. if err != nil {
  73. return err
  74. }
  75. //set telemetry timestamp for server, restarts 24 hour cycle
  76. return setTelemetryTimestamp(serverUUID)
  77. }
  78. // fetchTelemetry - fetches telemetry data: count of various object types in DB
  79. func fetchTelemetryData() (telemetryData, error) {
  80. var data telemetryData
  81. data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME)
  82. data.Users = getDBLength(database.USERS_TABLE_NAME)
  83. data.Networks = getDBLength(database.NETWORKS_TABLE_NAME)
  84. data.Version = servercfg.GetVersion()
  85. nodes, err := logic.GetAllNodes()
  86. if err == nil {
  87. data.Nodes = len(nodes)
  88. data.Count = getClientCount(nodes)
  89. }
  90. return data, err
  91. }
  92. // setTelemetryTimestamp - Give the entry in the DB a new timestamp
  93. func setTelemetryTimestamp(uuid string) error {
  94. lastsend := time.Now().Unix()
  95. var serverTelData = models.Telemetry{
  96. UUID: uuid,
  97. LastSend: lastsend,
  98. }
  99. jsonObj, err := json.Marshal(serverTelData)
  100. if err != nil {
  101. return err
  102. }
  103. err = database.Insert(database.SERVER_UUID_RECORD_KEY, string(jsonObj), database.SERVER_UUID_TABLE_NAME)
  104. return err
  105. }
  106. // getClientCount - returns counts of nodes with various OS types and conditions
  107. func getClientCount(nodes []models.Node) clientCount {
  108. var count clientCount
  109. for _, node := range nodes {
  110. switch node.OS {
  111. case "macos":
  112. count.MacOS += 1
  113. case "windows":
  114. count.Windows += 1
  115. case "linux":
  116. count.Linux += 1
  117. case "freebsd":
  118. count.FreeBSD += 1
  119. }
  120. if !(node.IsServer == "yes") {
  121. count.NonServer += 1
  122. }
  123. }
  124. return count
  125. }
  126. // fetchTelemetryRecord - get the existing UUID and Timestamp from the DB
  127. func fetchTelemetryRecord() (models.Telemetry, error) {
  128. var rawData string
  129. var telObj models.Telemetry
  130. var err error
  131. rawData, err = database.FetchRecord(database.SERVER_UUID_TABLE_NAME, database.SERVER_UUID_RECORD_KEY)
  132. if err != nil {
  133. return telObj, err
  134. }
  135. err = json.Unmarshal([]byte(rawData), &telObj)
  136. return telObj, err
  137. }
  138. // getDBLength - get length of DB to get count of objects
  139. func getDBLength(dbname string) int {
  140. data, err := database.FetchRecords(dbname)
  141. if err != nil {
  142. return 0
  143. }
  144. return len(data)
  145. }
  146. // telemetryData - What data to send to posthog
  147. type telemetryData struct {
  148. Nodes int
  149. ExtClients int
  150. Users int
  151. Count clientCount
  152. Networks int
  153. Version string
  154. }
  155. // clientCount - What types of netclients we're tallying
  156. type clientCount struct {
  157. MacOS int
  158. Windows int
  159. Linux int
  160. FreeBSD int
  161. K8S int
  162. Docker int
  163. NonServer int
  164. }