metrics.go 5.9 KB

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