telemetry.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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("hosts", d.Hosts).
  54. Set("servers", d.Servers).
  55. Set("non-server nodes", d.Count.NonServer).
  56. Set("extclients", d.ExtClients).
  57. Set("users", d.Users).
  58. Set("networks", d.Networks).
  59. Set("linux", d.Count.Linux).
  60. Set("darwin", d.Count.MacOS).
  61. Set("windows", d.Count.Windows).
  62. Set("freebsd", d.Count.FreeBSD).
  63. Set("docker", d.Count.Docker).
  64. Set("k8s", d.Count.K8S).
  65. Set("version", d.Version).
  66. Set("is_ee", isEE).
  67. Set("is_free_tier", isFreeTier),
  68. })
  69. }
  70. // fetchTelemetry - fetches telemetry data: count of various object types in DB
  71. func fetchTelemetryData() (telemetryData, error) {
  72. var data telemetryData
  73. data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME)
  74. data.Users = getDBLength(database.USERS_TABLE_NAME)
  75. data.Networks = getDBLength(database.NETWORKS_TABLE_NAME)
  76. data.Hosts = getDBLength(database.HOSTS_TABLE_NAME)
  77. data.Version = servercfg.GetVersion()
  78. data.Servers = getServerCount()
  79. nodes, err := GetAllNodes()
  80. if err == nil {
  81. data.Nodes = len(nodes)
  82. data.Count = getClientCount(nodes)
  83. }
  84. return data, err
  85. }
  86. // getServerCount returns number of servers from database
  87. func getServerCount() int {
  88. data, err := database.FetchRecords(database.SERVER_UUID_TABLE_NAME)
  89. if err != nil {
  90. logger.Log(0, "errror retrieving server data", err.Error())
  91. }
  92. return len(data)
  93. }
  94. // setTelemetryTimestamp - Give the entry in the DB a new timestamp
  95. func setTelemetryTimestamp(telRecord *models.Telemetry) error {
  96. lastsend := time.Now().Unix()
  97. var serverTelData = models.Telemetry{
  98. UUID: telRecord.UUID,
  99. LastSend: lastsend,
  100. TrafficKeyPriv: telRecord.TrafficKeyPriv,
  101. TrafficKeyPub: telRecord.TrafficKeyPub,
  102. }
  103. jsonObj, err := json.Marshal(&serverTelData)
  104. if err != nil {
  105. return err
  106. }
  107. err = database.Insert(database.SERVER_UUID_RECORD_KEY, string(jsonObj), database.SERVER_UUID_TABLE_NAME)
  108. return err
  109. }
  110. // getClientCount - returns counts of nodes with various OS types and conditions
  111. func getClientCount(nodes []models.Node) clientCount {
  112. var count clientCount
  113. for _, node := range nodes {
  114. host, err := GetHost(node.HostID.String())
  115. if err != nil {
  116. continue
  117. }
  118. switch host.OS {
  119. case "darwin":
  120. count.MacOS += 1
  121. case "windows":
  122. count.Windows += 1
  123. case "linux":
  124. count.Linux += 1
  125. case "freebsd":
  126. count.FreeBSD += 1
  127. }
  128. }
  129. return count
  130. }
  131. // fetchTelemetryRecord - get the existing UUID and Timestamp from the DB
  132. func fetchTelemetryRecord() (models.Telemetry, error) {
  133. var rawData string
  134. var telObj models.Telemetry
  135. var err error
  136. rawData, err = database.FetchRecord(database.SERVER_UUID_TABLE_NAME, database.SERVER_UUID_RECORD_KEY)
  137. if err != nil {
  138. return telObj, err
  139. }
  140. err = json.Unmarshal([]byte(rawData), &telObj)
  141. return telObj, err
  142. }
  143. // getDBLength - get length of DB to get count of objects
  144. func getDBLength(dbname string) int {
  145. data, err := database.FetchRecords(dbname)
  146. if err != nil {
  147. return 0
  148. }
  149. return len(data)
  150. }
  151. // telemetryData - What data to send to posthog
  152. type telemetryData struct {
  153. Nodes int
  154. Hosts int
  155. ExtClients int
  156. Users int
  157. Count clientCount
  158. Networks int
  159. Servers int
  160. Version string
  161. IsEE bool
  162. IsFreeTier bool
  163. }
  164. // clientCount - What types of netclients we're tallying
  165. type clientCount struct {
  166. MacOS int
  167. Windows int
  168. Linux int
  169. FreeBSD int
  170. K8S int
  171. Docker int
  172. NonServer int
  173. }