telemetry.go 4.6 KB

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