metrics.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package controllers
  2. import (
  3. "encoding/json"
  4. "math/rand"
  5. "net/http"
  6. "time"
  7. "github.com/gorilla/mux"
  8. "github.com/gravitl/netmaker/database"
  9. "github.com/gravitl/netmaker/logger"
  10. "github.com/gravitl/netmaker/logic"
  11. "github.com/gravitl/netmaker/models"
  12. proLogic "github.com/gravitl/netmaker/pro/logic"
  13. "golang.org/x/exp/slog"
  14. )
  15. // MetricHandlers - How we handle Pro Metrics
  16. func MetricHandlers(r *mux.Router) {
  17. r.HandleFunc("/api/metrics/{network}/{nodeid}", logic.SecurityCheck(true, http.HandlerFunc(getNodeMetrics))).Methods(http.MethodGet)
  18. r.HandleFunc("/api/metrics/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkNodesMetrics))).Methods(http.MethodGet)
  19. r.HandleFunc("/api/metrics", logic.SecurityCheck(true, http.HandlerFunc(getAllMetrics))).Methods(http.MethodGet)
  20. r.HandleFunc("/api/metrics-ext/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkExtMetrics))).Methods(http.MethodGet)
  21. }
  22. // get the metrics of a given node
  23. func getNodeMetrics(w http.ResponseWriter, r *http.Request) {
  24. // set header.
  25. w.Header().Set("Content-Type", "application/json")
  26. var params = mux.Vars(r)
  27. nodeID := params["nodeid"]
  28. logger.Log(1, r.Header.Get("user"), "requested fetching metrics for node", nodeID, "on network", params["network"])
  29. metrics, err := logic.GetMetrics(nodeID)
  30. if err != nil {
  31. logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of node", nodeID, err.Error())
  32. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  33. return
  34. }
  35. logger.Log(1, r.Header.Get("user"), "fetched metrics for node", params["nodeid"])
  36. w.WriteHeader(http.StatusOK)
  37. json.NewEncoder(w).Encode(metrics)
  38. }
  39. // get the metrics of all nodes in given network
  40. func getNetworkNodesMetrics(w http.ResponseWriter, r *http.Request) {
  41. // set header.
  42. w.Header().Set("Content-Type", "application/json")
  43. var params = mux.Vars(r)
  44. network := params["network"]
  45. logger.Log(1, r.Header.Get("user"), "requested fetching network node metrics on network", network)
  46. networkNodes, err := logic.GetNetworkNodes(network)
  47. if err != nil {
  48. logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of all nodes in network", network, err.Error())
  49. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  50. return
  51. }
  52. networkMetrics := models.NetworkMetrics{}
  53. networkMetrics.Nodes = make(models.MetricsMap)
  54. for i := range networkNodes {
  55. id := networkNodes[i].ID
  56. // metrics, err := proLogic.GetMetrics(id.String())
  57. // if err != nil {
  58. // logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id.String(), "during network metrics fetch", err.Error())
  59. // continue
  60. // }
  61. host, _ := logic.GetHost(networkNodes[i].HostID.String())
  62. metrics := &models.Metrics{
  63. Network: networkNodes[i].Network,
  64. NodeID: id.String(),
  65. NodeName: host.Name,
  66. Connectivity: make(map[string]models.Metric),
  67. }
  68. for _, node := range networkNodes {
  69. if node.ID == id {
  70. continue
  71. }
  72. m := models.Metric{}
  73. m.Connected = true
  74. m.ActualUptime = time.Duration(time.Hour * time.Duration(rand.Intn(50)))
  75. m.Latency = int64(rand.Intn(10))
  76. m.PercentUp = float64(rand.Intn(100-90+1) + 90)
  77. m.TotalSent = int64(rand.Intn(10000))
  78. m.TotalReceived = int64(rand.Intn(10000))
  79. m.Uptime = int64(rand.Intn(10000))
  80. metrics.Connectivity[node.ID.String()] = m
  81. }
  82. networkMetrics.Nodes[id.String()] = *metrics
  83. }
  84. logger.Log(1, r.Header.Get("user"), "fetched metrics for network", network)
  85. w.WriteHeader(http.StatusOK)
  86. json.NewEncoder(w).Encode(networkMetrics)
  87. }
  88. // get the metrics for ext clients on a given network
  89. func getNetworkExtMetrics(w http.ResponseWriter, r *http.Request) {
  90. // set header.
  91. w.Header().Set("Content-Type", "application/json")
  92. var params = mux.Vars(r)
  93. network := params["network"]
  94. logger.Log(1, r.Header.Get("user"), "requested fetching external client metrics on network", network)
  95. ingresses, err := proLogic.GetNetworkIngresses(network) // grab all the ingress gateways
  96. if err != nil {
  97. logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of ext clients in network", network, err.Error())
  98. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  99. return
  100. }
  101. clients, err := logic.GetNetworkExtClients(network) // grab all the network ext clients
  102. if err != nil {
  103. if database.IsEmptyRecord(err) {
  104. var metrics struct{}
  105. w.WriteHeader(http.StatusOK)
  106. json.NewEncoder(w).Encode(metrics)
  107. return
  108. }
  109. logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of ext clients in network", network, err.Error())
  110. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  111. return
  112. }
  113. networkMetrics := models.Metrics{}
  114. networkMetrics.Connectivity = make(map[string]models.Metric)
  115. for i := range ingresses {
  116. id := ingresses[i].ID
  117. ingressMetrics, err := proLogic.GetMetrics(id.String())
  118. if err != nil {
  119. logger.Log(1, r.Header.Get("user"), "failed to append external client metrics from ingress node", id.String(), err.Error())
  120. continue
  121. }
  122. if ingressMetrics.Connectivity == nil {
  123. continue
  124. }
  125. for j := range clients {
  126. if clients[j].Network != network {
  127. continue
  128. }
  129. // if metrics for that client have been reported, append them
  130. if _, ok := ingressMetrics.Connectivity[clients[j].ClientID]; ok {
  131. networkMetrics.Connectivity[clients[j].ClientID] = ingressMetrics.Connectivity[clients[j].ClientID]
  132. }
  133. }
  134. }
  135. slog.Debug("sending collected client metrics", "metrics", networkMetrics.Connectivity)
  136. logger.Log(1, r.Header.Get("user"), "fetched ext client metrics for network", network)
  137. w.WriteHeader(http.StatusOK)
  138. json.NewEncoder(w).Encode(networkMetrics.Connectivity)
  139. }
  140. // get Metrics of all nodes on server, lots of data
  141. func getAllMetrics(w http.ResponseWriter, r *http.Request) {
  142. w.Header().Set("Content-Type", "application/json")
  143. logger.Log(1, r.Header.Get("user"), "requested fetching all metrics")
  144. allNodes, err := logic.GetAllNodes()
  145. if err != nil {
  146. logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of all nodes on server", err.Error())
  147. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  148. return
  149. }
  150. networkMetrics := models.NetworkMetrics{}
  151. networkMetrics.Nodes = make(models.MetricsMap)
  152. for i := range allNodes {
  153. id := allNodes[i].ID
  154. metrics, err := proLogic.GetMetrics(id.String())
  155. if err != nil {
  156. logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id.String(), "during all nodes metrics fetch", err.Error())
  157. continue
  158. }
  159. networkMetrics.Nodes[id.String()] = *metrics
  160. }
  161. logger.Log(1, r.Header.Get("user"), "fetched metrics for all nodes on server")
  162. w.WriteHeader(http.StatusOK)
  163. json.NewEncoder(w).Encode(networkMetrics)
  164. }