telemetry.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. // posthog_pub_key - Key for sending data to PostHog
  14. const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES"
  15. // posthog_endpoint - Endpoint of PostHog server
  16. const posthog_endpoint = "https://app.posthog.com"
  17. // setFreeTierForTelemetry - store free tier flag without having an import cycle when used for telemetry
  18. // (as the pro package needs the logic package as currently written).
  19. func SetFreeTierForTelemetry(freeTierFlag bool) {
  20. isFreeTier = freeTierFlag
  21. }
  22. // sendTelemetry - gathers telemetry data and sends to posthog
  23. func sendTelemetry() error {
  24. if servercfg.Telemetry() == "off" {
  25. return nil
  26. }
  27. var telRecord, err = FetchTelemetryRecord()
  28. if err != nil {
  29. return err
  30. }
  31. // get telemetry data
  32. d, err := FetchTelemetryData()
  33. if err != nil {
  34. return err
  35. }
  36. client, err := posthog.NewWithConfig(posthog_pub_key, posthog.Config{Endpoint: posthog_endpoint})
  37. if err != nil {
  38. return err
  39. }
  40. defer client.Close()
  41. // send to posthog
  42. return client.Enqueue(posthog.Capture{
  43. DistinctId: telRecord.UUID,
  44. Event: "daily checkin",
  45. Properties: posthog.NewProperties().
  46. Set("nodes", d.Nodes).
  47. Set("hosts", d.Hosts).
  48. Set("servers", d.Servers).
  49. Set("non-server nodes", d.Count.NonServer).
  50. Set("extclients", d.ExtClients).
  51. Set("users", d.Users).
  52. Set("networks", d.Networks).
  53. Set("linux", d.Count.Linux).
  54. Set("darwin", d.Count.MacOS).
  55. Set("windows", d.Count.Windows).
  56. Set("freebsd", d.Count.FreeBSD).
  57. Set("docker", d.Count.Docker).
  58. Set("k8s", d.Count.K8S).
  59. Set("version", d.Version).
  60. Set("is_ee", d.IsPro). // TODO change is_ee to is_pro for consistency, but probably needs changes in posthog
  61. Set("is_free_tier", isFreeTier),
  62. })
  63. }
  64. // FetchTelemetryData - fetches telemetry data: count of various object types in DB
  65. func FetchTelemetryData() (telemetryData, error) {
  66. var data telemetryData
  67. data.IsPro = servercfg.IsPro
  68. data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME)
  69. data.Users = getDBLength(database.USERS_TABLE_NAME)
  70. data.Networks = getDBLength(database.NETWORKS_TABLE_NAME)
  71. data.Hosts = getDBLength(database.HOSTS_TABLE_NAME)
  72. data.Version = servercfg.GetVersion()
  73. data.Servers = getServerCount()
  74. nodes, err := GetAllNodes()
  75. if err == nil {
  76. data.Nodes = len(nodes)
  77. data.Count = getClientCount(nodes)
  78. }
  79. return data, err
  80. }
  81. // getServerCount returns number of servers from database
  82. func getServerCount() int {
  83. data, err := database.FetchRecords(database.SERVER_UUID_TABLE_NAME)
  84. if err != nil {
  85. logger.Log(0, "errror retrieving server data", err.Error())
  86. }
  87. return len(data)
  88. }
  89. // setTelemetryTimestamp - Give the entry in the DB a new timestamp
  90. func setTelemetryTimestamp(telRecord *models.Telemetry) error {
  91. lastsend := time.Now().Unix()
  92. var serverTelData = models.Telemetry{
  93. UUID: telRecord.UUID,
  94. LastSend: lastsend,
  95. TrafficKeyPriv: telRecord.TrafficKeyPriv,
  96. TrafficKeyPub: telRecord.TrafficKeyPub,
  97. }
  98. jsonObj, err := json.Marshal(&serverTelData)
  99. if err != nil {
  100. return err
  101. }
  102. err = database.Insert(database.SERVER_UUID_RECORD_KEY, string(jsonObj), database.SERVER_UUID_TABLE_NAME)
  103. return err
  104. }
  105. // getClientCount - returns counts of nodes with various OS types and conditions
  106. func getClientCount(nodes []models.Node) clientCount {
  107. var count clientCount
  108. for _, node := range nodes {
  109. host, err := GetHost(node.HostID.String())
  110. if err != nil {
  111. continue
  112. }
  113. switch host.OS {
  114. case "darwin":
  115. count.MacOS += 1
  116. case "windows":
  117. count.Windows += 1
  118. case "linux":
  119. count.Linux += 1
  120. case "freebsd":
  121. count.FreeBSD += 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. Hosts int
  150. ExtClients int
  151. Users int
  152. Count clientCount
  153. Networks int
  154. Servers int
  155. Version string
  156. IsPro bool
  157. IsFreeTier bool
  158. }
  159. // clientCount - What types of netclients we're tallying
  160. type clientCount struct {
  161. MacOS int
  162. Windows int
  163. Linux int
  164. FreeBSD int
  165. K8S int
  166. Docker int
  167. NonServer int
  168. }