telemetry.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. switch node.OS {
  104. case "darwin":
  105. count.MacOS += 1
  106. case "windows":
  107. count.Windows += 1
  108. case "linux":
  109. count.Linux += 1
  110. case "freebsd":
  111. count.FreeBSD += 1
  112. }
  113. if !(node.IsServer == "yes") {
  114. count.NonServer += 1
  115. }
  116. }
  117. return count
  118. }
  119. // fetchTelemetryRecord - get the existing UUID and Timestamp from the DB
  120. func fetchTelemetryRecord() (models.Telemetry, error) {
  121. var rawData string
  122. var telObj models.Telemetry
  123. var err error
  124. rawData, err = database.FetchRecord(database.SERVER_UUID_TABLE_NAME, database.SERVER_UUID_RECORD_KEY)
  125. if err != nil {
  126. return telObj, err
  127. }
  128. err = json.Unmarshal([]byte(rawData), &telObj)
  129. return telObj, err
  130. }
  131. // getDBLength - get length of DB to get count of objects
  132. func getDBLength(dbname string) int {
  133. data, err := database.FetchRecords(dbname)
  134. if err != nil {
  135. return 0
  136. }
  137. return len(data)
  138. }
  139. // telemetryData - What data to send to posthog
  140. type telemetryData struct {
  141. Nodes int
  142. ExtClients int
  143. Users int
  144. Count clientCount
  145. Networks int
  146. Servers int
  147. Version string
  148. IsEE bool
  149. IsFreeTier bool
  150. }
  151. // clientCount - What types of netclients we're tallying
  152. type clientCount struct {
  153. MacOS int
  154. Windows int
  155. Linux int
  156. FreeBSD int
  157. K8S int
  158. Docker int
  159. NonServer int
  160. }