telemetry.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package logic
  2. import (
  3. "encoding/json"
  4. "time"
  5. "github.com/gravitl/netmaker/database"
  6. "github.com/gravitl/netmaker/logger"
  7. "github.com/gravitl/netmaker/models"
  8. "github.com/gravitl/netmaker/servercfg"
  9. "github.com/posthog/posthog-go"
  10. )
  11. // flags to keep for telemetry
  12. var isFreeTier bool
  13. var isEE bool
  14. // posthog_pub_key - Key for sending data to PostHog
  15. const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES"
  16. // posthog_endpoint - Endpoint of PostHog server
  17. const posthog_endpoint = "https://app.posthog.com"
  18. // setEEForTelemetry - store EE flag without having an import cycle when used for telemetry
  19. // (as the ee package needs the logic package as currently written).
  20. func SetEEForTelemetry(eeFlag bool) {
  21. isEE = eeFlag
  22. }
  23. // setFreeTierForTelemetry - store free tier flag without having an import cycle when used for telemetry
  24. // (as the ee package needs the logic package as currently written).
  25. func SetFreeTierForTelemetry(freeTierFlag bool) {
  26. isFreeTier = freeTierFlag
  27. }
  28. // sendTelemetry - gathers telemetry data and sends to posthog
  29. func sendTelemetry() error {
  30. if servercfg.Telemetry() == "off" {
  31. return nil
  32. }
  33. var telRecord, err = fetchTelemetryRecord()
  34. if err != nil {
  35. return err
  36. }
  37. // get telemetry data
  38. d, err := fetchTelemetryData()
  39. if err != nil {
  40. return err
  41. }
  42. client, err := posthog.NewWithConfig(posthog_pub_key, posthog.Config{Endpoint: posthog_endpoint})
  43. if err != nil {
  44. return err
  45. }
  46. defer client.Close()
  47. // send to posthog
  48. return client.Enqueue(posthog.Capture{
  49. DistinctId: telRecord.UUID,
  50. Event: "daily checkin",
  51. Properties: posthog.NewProperties().
  52. Set("nodes", d.Nodes).
  53. Set("servers", d.Servers).
  54. Set("non-server nodes", d.Count.NonServer).
  55. Set("extclients", d.ExtClients).
  56. Set("users", d.Users).
  57. Set("networks", d.Networks).
  58. Set("linux", d.Count.Linux).
  59. Set("darwin", d.Count.MacOS).
  60. Set("windows", d.Count.Windows).
  61. Set("freebsd", d.Count.FreeBSD).
  62. Set("docker", d.Count.Docker).
  63. Set("k8s", d.Count.K8S).
  64. Set("version", d.Version).
  65. Set("is_ee", isEE).
  66. Set("is_free_tier", isFreeTier),
  67. })
  68. }
  69. // fetchTelemetry - fetches telemetry data: count of various object types in DB
  70. func fetchTelemetryData() (telemetryData, error) {
  71. var data telemetryData
  72. data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME)
  73. data.Users = getDBLength(database.USERS_TABLE_NAME)
  74. data.Networks = getDBLength(database.NETWORKS_TABLE_NAME)
  75. data.Version = servercfg.GetVersion()
  76. data.Servers = getServerCount()
  77. nodes, err := GetAllNodes()
  78. if err == nil {
  79. data.Nodes = len(nodes)
  80. data.Count = getClientCount(nodes)
  81. }
  82. return data, err
  83. }
  84. // getServerCount returns number of servers from database
  85. func getServerCount() int {
  86. data, err := database.FetchRecords(database.SERVER_UUID_TABLE_NAME)
  87. if err != nil {
  88. logger.Log(0, "errror retrieving server data", err.Error())
  89. }
  90. return len(data)
  91. }
  92. // setTelemetryTimestamp - Give the entry in the DB a new timestamp
  93. func setTelemetryTimestamp(telRecord *models.Telemetry) error {
  94. lastsend := time.Now().Unix()
  95. var serverTelData = models.Telemetry{
  96. UUID: telRecord.UUID,
  97. LastSend: lastsend,
  98. TrafficKeyPriv: telRecord.TrafficKeyPriv,
  99. TrafficKeyPub: telRecord.TrafficKeyPub,
  100. }
  101. jsonObj, err := json.Marshal(&serverTelData)
  102. if err != nil {
  103. return err
  104. }
  105. err = database.Insert(database.SERVER_UUID_RECORD_KEY, string(jsonObj), database.SERVER_UUID_TABLE_NAME)
  106. return err
  107. }
  108. // getClientCount - returns counts of nodes with various OS types and conditions
  109. func getClientCount(nodes []models.Node) clientCount {
  110. var count clientCount
  111. for _, node := range nodes {
  112. host, err := GetHost(node.HostID.String())
  113. if err != nil {
  114. continue
  115. }
  116. switch host.OS {
  117. case "darwin":
  118. count.MacOS += 1
  119. case "windows":
  120. count.Windows += 1
  121. case "linux":
  122. count.Linux += 1
  123. case "freebsd":
  124. count.FreeBSD += 1
  125. }
  126. }
  127. return count
  128. }
  129. // fetchTelemetryRecord - get the existing UUID and Timestamp from the DB
  130. func fetchTelemetryRecord() (models.Telemetry, error) {
  131. var rawData string
  132. var telObj models.Telemetry
  133. var err error
  134. rawData, err = database.FetchRecord(database.SERVER_UUID_TABLE_NAME, database.SERVER_UUID_RECORD_KEY)
  135. if err != nil {
  136. return telObj, err
  137. }
  138. err = json.Unmarshal([]byte(rawData), &telObj)
  139. return telObj, err
  140. }
  141. // getDBLength - get length of DB to get count of objects
  142. func getDBLength(dbname string) int {
  143. data, err := database.FetchRecords(dbname)
  144. if err != nil {
  145. return 0
  146. }
  147. return len(data)
  148. }
  149. // telemetryData - What data to send to posthog
  150. type telemetryData struct {
  151. Nodes int
  152. ExtClients int
  153. Users int
  154. Count clientCount
  155. Networks int
  156. Servers int
  157. Version string
  158. IsEE bool
  159. IsFreeTier bool
  160. }
  161. // clientCount - What types of netclients we're tallying
  162. type clientCount struct {
  163. MacOS int
  164. Windows int
  165. Linux int
  166. FreeBSD int
  167. K8S int
  168. Docker int
  169. NonServer int
  170. }