Browse Source

Merge pull request #1651 from gravitl/feature_v0.16.2_client_metrics

Feature v0.16.2 client metrics
Alex Feiszli 2 years ago
parent
commit
4a9e5580fa
4 changed files with 117 additions and 3 deletions
  1. 53 0
      ee/ee_controllers/metrics.go
  2. 40 0
      logic/metrics.go
  3. 15 0
      logic/nodes.go
  4. 9 3
      mq/handlers.go

+ 53 - 0
ee/ee_controllers/metrics.go

@@ -15,6 +15,7 @@ func MetricHandlers(r *mux.Router) {
 	r.HandleFunc("/api/metrics/{network}/{nodeid}", logic.SecurityCheck(true, http.HandlerFunc(getNodeMetrics))).Methods("GET")
 	r.HandleFunc("/api/metrics/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkNodesMetrics))).Methods("GET")
 	r.HandleFunc("/api/metrics", logic.SecurityCheck(true, http.HandlerFunc(getAllMetrics))).Methods("GET")
+	r.HandleFunc("/api/metrics-ext/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkExtMetrics))).Methods("GET")
 }
 
 // get the metrics of a given node
@@ -72,6 +73,58 @@ func getNetworkNodesMetrics(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(networkMetrics)
 }
 
+// get the metrics for ext clients on a given network
+func getNetworkExtMetrics(w http.ResponseWriter, r *http.Request) {
+	// set header.
+	w.Header().Set("Content-Type", "application/json")
+
+	var params = mux.Vars(r)
+	network := params["network"]
+
+	logger.Log(1, r.Header.Get("user"), "requested fetching external client metrics on network", network)
+	ingresses, err := logic.GetNetworkIngresses(network) // grab all the ingress gateways
+	if err != nil {
+		logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of ext clients in network", network, err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+
+	clients, err := logic.GetNetworkExtClients(network) // grab all the network ext clients
+	if err != nil {
+		logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of ext clients in network", network, err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+
+	networkMetrics := models.Metrics{}
+	networkMetrics.Connectivity = make(map[string]models.Metric)
+
+	for i := range ingresses {
+		id := ingresses[i].ID
+		ingressMetrics, err := logic.GetMetrics(id)
+		if err != nil {
+			logger.Log(1, r.Header.Get("user"), "failed to append external client metrics from ingress node", id, err.Error())
+			continue
+		}
+		if ingressMetrics.Connectivity == nil {
+			continue
+		}
+		for j := range clients {
+			if clients[j].Network != network {
+				continue
+			}
+			// if metrics for that client have been reported, append them
+			if len(ingressMetrics.Connectivity[clients[j].ClientID].NodeName) > 0 {
+				networkMetrics.Connectivity[clients[j].ClientID] = ingressMetrics.Connectivity[clients[j].ClientID]
+			}
+		}
+	}
+
+	logger.Log(1, r.Header.Get("user"), "fetched ext client metrics for network", network)
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(networkMetrics.Connectivity)
+}
+
 // get Metrics of all nodes on server, lots of data
 func getAllMetrics(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")

+ 40 - 0
logic/metrics.go

@@ -5,6 +5,7 @@ import (
 
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/wireguard"
 )
 
 // GetMetrics - gets the metrics
@@ -42,9 +43,11 @@ func DeleteMetrics(nodeid string) error {
 func CollectServerMetrics(serverID string, networkNodes []models.Node) *models.Metrics {
 	newServerMetrics := models.Metrics{}
 	newServerMetrics.Connectivity = make(map[string]models.Metric)
+	var serverNode models.Node
 	for i := range networkNodes {
 		currNodeID := networkNodes[i].ID
 		if currNodeID == serverID {
+			serverNode = networkNodes[i]
 			continue
 		}
 		if currMetrics, err := GetMetrics(currNodeID); err == nil {
@@ -61,5 +64,42 @@ func CollectServerMetrics(serverID string, networkNodes []models.Node) *models.M
 			}
 		}
 	}
+
+	if serverNode.IsIngressGateway == "yes" {
+		clients, err := GetExtClientsByID(serverID, serverNode.Network)
+		if err == nil {
+			peers, err := wireguard.GetDevicePeers(serverNode.Interface)
+			if err == nil {
+				for i := range clients {
+					for j := range peers {
+						if clients[i].PublicKey == peers[j].PublicKey.String() {
+							if peers[j].ReceiveBytes > 0 &&
+								peers[j].TransmitBytes > 0 {
+								newServerMetrics.Connectivity[clients[i].ClientID] = models.Metric{
+									NodeName:      clients[i].ClientID,
+									TotalTime:     5,
+									Uptime:        5,
+									IsServer:      "no",
+									TotalReceived: peers[j].ReceiveBytes,
+									TotalSent:     peers[j].TransmitBytes,
+									Connected:     true,
+								}
+							} else {
+								newServerMetrics.Connectivity[clients[i].ClientID] = models.Metric{
+									NodeName:  clients[i].ClientID,
+									TotalTime: 5,
+									Uptime:    0,
+									IsServer:  "no",
+									Connected: false,
+									Latency:   999,
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
 	return &newServerMetrics
 }

+ 15 - 0
logic/nodes.go

@@ -741,6 +741,21 @@ func findNode(ip string) (*models.Node, error) {
 	return nil, errors.New("node not found")
 }
 
+// GetNetworkIngresses - gets the gateways of a network
+func GetNetworkIngresses(network string) ([]models.Node, error) {
+	var ingresses []models.Node
+	netNodes, err := GetNetworkNodes(network)
+	if err != nil {
+		return []models.Node{}, err
+	}
+	for i := range netNodes {
+		if netNodes[i].IsIngressGateway == "yes" {
+			ingresses = append(ingresses, netNodes[i])
+		}
+	}
+	return ingresses, nil
+}
+
 // == PRO ==
 
 func updateProNodeACLS(node *models.Node) error {

+ 9 - 3
mq/handlers.go

@@ -242,10 +242,16 @@ func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) boo
 		// associate ext clients with IDs
 		for i := range attachedClients {
 			extMetric := newMetrics.Connectivity[attachedClients[i].PublicKey]
-			delete(newMetrics.Connectivity, attachedClients[i].PublicKey)
-			if extMetric.Connected { // add ext client metrics
-				newMetrics.Connectivity[attachedClients[i].ClientID] = extMetric
+			if len(extMetric.NodeName) == 0 { // cover server clients
+				extMetric = newMetrics.Connectivity[attachedClients[i].ClientID]
+				if extMetric.TotalReceived > 0 && extMetric.TotalSent > 0 {
+					extMetric.Connected = true
+				}
 			}
+			extMetric.NodeName = attachedClients[i].ClientID
+			extMetric.IsServer = "no"
+			delete(newMetrics.Connectivity, attachedClients[i].PublicKey)
+			newMetrics.Connectivity[attachedClients[i].ClientID] = extMetric
 		}
 	}