diff --git a/ee/ee_controllers/metrics.go b/ee/ee_controllers/metrics.go index 409682a2..5479103b 100644 --- a/ee/ee_controllers/metrics.go +++ b/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(getAllMetrics))).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.NetworkMetrics{} + networkMetrics.Nodes = make(models.MetricsMap) + + 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.Nodes[clients[j].ClientID] = *ingressMetrics + } + } + } + + logger.Log(1, r.Header.Get("user"), "fetched ext client metrics for network", network) + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(networkMetrics) +} + // 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") diff --git a/logic/metrics.go b/logic/metrics.go index f60bcd76..fed3ac75 100644 --- a/logic/metrics.go +++ b/logic/metrics.go @@ -2,9 +2,11 @@ package logic import ( "encoding/json" + "time" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/wireguard" ) // GetMetrics - gets the metrics @@ -42,9 +44,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 +65,43 @@ 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].LastHandshakeTime.Before(time.Now().Add(-(time.Minute * 3))) && + peers[j].ReceiveBytes > 0 && + peers[j].TransmitBytes > 0 { + newServerMetrics.Connectivity[clients[i].ClientID] = models.Metric{ + NodeName: clients[i].ClientID, + TotalTime: 1, + Uptime: 1, + 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: 1, + Uptime: 0, + IsServer: "no", + Connected: false, + Latency: 999, + } + } + } + } + } + } + } + } + return &newServerMetrics } diff --git a/logic/nodes.go b/logic/nodes.go index 12e4aabf..0106fb20 100644 --- a/logic/nodes.go +++ b/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 { diff --git a/mq/handlers.go b/mq/handlers.go index 9638043f..1843c521 100644 --- a/mq/handlers.go +++ b/mq/handlers.go @@ -238,10 +238,10 @@ func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) boo // associate ext clients with IDs for i := range attachedClients { extMetric := newMetrics.Connectivity[attachedClients[i].PublicKey] + extMetric.NodeName = attachedClients[i].ClientID + extMetric.IsServer = "no" delete(newMetrics.Connectivity, attachedClients[i].PublicKey) - if extMetric.Connected { // add ext client metrics - newMetrics.Connectivity[attachedClients[i].ClientID] = extMetric - } + newMetrics.Connectivity[attachedClients[i].ClientID] = extMetric } }