package a_status import ( "encoding/json" "errors" "fmt" "github.com/shirou/gopsutil/v3/net" "io" net2 "net" "net/http" "regexp" "strconv" "strings" "time" "wdd.io/agent-common/utils" ) type NetworkMetric struct { net.IOCountersStat SendSpeed float64 RecvSpeed float64 } type PublicNetworkInfo struct { IP string `json:"ip,omitempty"` City string `json:"city,omitempty"` Region string `json:"region,omitempty"` Country string `json:"country,omitempty"` Loc string `json:"loc,omitempty"` Org string `json:"org,omitempty"` Postal string `json:"postal,omitempty"` Timezone string `json:"timezone,omitempty"` } func (pn *PublicNetworkInfo) GetPublicNetworkInfo() { url := "https://ipinfo.io" req, err := http.NewRequest("GET", url, nil) if err != nil { fmt.Println(err) return } req.Header.Set("Authorization", "Bearer 6ecb0db9bd8f19") client := &http.Client{ Timeout: 5 * time.Second, // set timeout to 10 seconds } resp, err := client.Do(req) if err != nil { fmt.Println(err) return } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { fmt.Println(err) return } err = json.Unmarshal(body, &pn) if err != nil { fmt.Println(err) return } //utils.BeautifulPrint(pn) } type NetworkInfo struct { Name string `json:"name"` // e.g., "en0", "lo0", "eth0.100" MTU int `json:"mtu"` // maximum transmission unit HardwareAddr string `json:"hardwareAddr"` // IEEE MAC-48, EUI-48 and EUI-64 form Flags []string `json:"flags"` // e.g., FlagUp, FlagLoopback, FlagMulticast InternalIPv4 []string `json:"internal_ip_v4,omitempty"` InternalIPv6 []string `json:"internal_ip_v6,omitempty"` ExternalIPv4 []string `json:"external_ip_v4,omitempty"` ExternalIPv6 []string `json:"external_ip_v6,omitempty"` } type NetworkStatus struct { Name string `json:"name,omitempty"` InternalIPv4 []string `json:"internal_ip_v4,omitempty"` InternalIPv6 []string `json:"internal_ip_v6,omitempty"` ExternalIPv4 []string `json:"external_ip_v4,omitempty"` ExternalIPv6 []string `json:"external_ip_v6,omitempty"` Mac string `json:"mac,omitempty"` Sent uint64 `json:"sent,omitempty"` Recv uint64 `json:"recv,omitempty"` SentRate string `json:"sent_rate,omitempty"` RecvRate string `json:"recv_rate,omitempty"` } func GetNetworkMetric() ([]NetworkMetric, error) { interfaceStatList, err := net.Interfaces() if err != nil { log.ErrorF("[GetNetworkMetric] - get interface list error %v\n", err) return nil, err } contains := false for _, interfaceStat := range interfaceStatList { if MatchNetInterfaceRight(interfaceStat.Name) { contains = true break } } if !contains { msg := "[GetNetworkMetric]- can not find desired net interface !" log.Warn(msg) return nil, errors.New(msg) } ioCountersStats, err := net.IOCounters(true) if err != nil { log.ErrorF("[GetNetworkMetric] - get io counter list error %v\n", err) return nil, err } //marshal, _ := json.Marshal(ioCountersStats) //fmt.Println(string(marshal)) duration := time.Second * 2 log.DebugF("[GetNetworkMetric] - start to wait %d seconds ", duration/1000000000) time.Sleep(duration) afterIoCounterList, err := net.IOCounters(true) if err != nil { log.ErrorF("[GetNetworkMetric] - get io counter list second error %v\n", err) return nil, err } var result []NetworkMetric for _, interfaceStat := range interfaceStatList { if MatchNetInterfaceRight(interfaceStat.Name) { log.DebugF("[GetNetworkMetric] - match net interface name is => %s", interfaceStat.Name) for _, after := range afterIoCounterList { if strings.HasPrefix(after.Name, interfaceStat.Name) { for _, before := range ioCountersStats { if strings.HasPrefix(before.Name, interfaceStat.Name) { // match after and before interface // assign networkMetric := NetworkMetric{ IOCountersStat: after, SendSpeed: 0, RecvSpeed: 0, } // calculate speed networkMetric.SendSpeed = (float64(after.BytesSent - before.BytesSent)) / duration.Seconds() networkMetric.RecvSpeed = (float64(after.BytesRecv - before.BytesRecv)) / duration.Seconds() // append result result = append(result, networkMetric) } } } } } } return result, nil } func GetNetworkInfo() ([]NetworkInfo, error) { interfaceStatList, err := net.Interfaces() if err != nil { log.ErrorF("[GetNetworkInfo] - get net interface list error %s", err.Error()) } var result []NetworkInfo for _, interfaceStat := range interfaceStatList { if MatchNetInterfaceRight(interfaceStat.Name) { // just collect useful net interface // new result networkInfo := NetworkInfo{ Name: interfaceStat.Name, MTU: interfaceStat.MTU, HardwareAddr: interfaceStat.HardwareAddr, Flags: interfaceStat.Flags, InternalIPv4: []string{}, InternalIPv6: []string{}, ExternalIPv4: nil, ExternalIPv6: nil, } // calculate real ip addr for _, interfaceAddr := range interfaceStat.Addrs { ip, cidr, err := net2.ParseCIDR(interfaceAddr.Addr) if err != nil { log.ErrorF("[GetNetworkInfo] - parse interface addr error %v", err) continue } // get the mask size maskLength, _ := cidr.Mask.Size() if ip.To4() != nil { networkInfo.InternalIPv4 = append(networkInfo.InternalIPv4, ip.String()+"/"+strconv.Itoa(maskLength)) } else if ip.To16() != nil { networkInfo.InternalIPv6 = append(networkInfo.InternalIPv6, ip.String()+"/"+strconv.Itoa(maskLength)) } } // assign result = append(result, networkInfo) } } return result, nil } func GetLocalHostIP() string { interfaceStatList, err := net.Interfaces() if err != nil { log.ErrorF("[GetLocalHostIP] -- error %s", err.Error()) return "" } utils.BeautifulPrint(interfaceStatList) return "" } func GetNetworkConnectionALl() []net.ConnectionStat { connections, err := net.Connections("all") if err != nil { log.ErrorF("[GetNetworkConnectionALl] - get network connections error ! %v", err) return nil } for _, con := range connections { fmt.Println() marshal, _ := json.Marshal(con) fmt.Println(string(marshal)) fmt.Println() } return connections } func GetNetworkConnectionTCP4() { } func GetNetworkConnectionTCP6() { connections, _ := net.Connections("tcp6") for _, con := range connections { fmt.Println() marshal, _ := json.Marshal(con) fmt.Println(string(marshal)) fmt.Println() } } func GetNetworkConnectionUDP4() { } func GetNetworkConnectionUDP6() { } func GetNetworkStatus() (*NetworkStatus, error) { interfaces, err := net.Interfaces() if err != nil { return nil, err } var mainInterface net.InterfaceStat for _, intf := range interfaces { if strings.HasPrefix(intf.Name, "ens") || strings.HasPrefix(intf.Name, "eth") || strings.HasPrefix(intf.Name, "eno") { mainInterface = intf break } } var allAddrs []string log.DebugF("all main interface address are %v", mainInterface.Addrs) for _, addr := range mainInterface.Addrs { allAddrs = append(allAddrs, addr.Addr) } ipv4List, ipv6List := GetInternalIpAdders(allAddrs) log.DebugF("ipv4 list are => %v, ipv6 list are => %v", ipv4List, ipv6List) counters, err := net.IOCounters(true) if err != nil { return nil, err } var sent uint64 var recv uint64 for _, counter := range counters { if counter.Name == mainInterface.Name { sent = counter.BytesSent recv = counter.BytesRecv break } } // 休眠3秒 time.Sleep(3 * time.Second) var sentAfter uint64 var recvAfter uint64 countersAfter, err := net.IOCounters(true) if err != nil { return nil, err } for _, counter := range countersAfter { if counter.Name == mainInterface.Name { sentAfter = counter.BytesSent recvAfter = counter.BytesRecv break } } sendRate := fmt.Sprintf(formatBytes((sentAfter-sent)/3) + "/s") recvRate := fmt.Sprintf(formatBytes((recvAfter-recv)/3) + "/s") info := &NetworkStatus{ Name: mainInterface.Name, InternalIPv4: ipv4List, InternalIPv6: ipv6List, ExternalIPv4: nil, ExternalIPv6: nil, Mac: mainInterface.HardwareAddr, Sent: sent, Recv: recv, SentRate: sendRate, RecvRate: recvRate, } return info, nil } func formatBytes(bytes uint64) string { const unit = 1024 if bytes < unit { return fmt.Sprintf("%d B", bytes) } div, exp := int64(unit), 0 for n := bytes / unit; n >= unit; n /= unit { div *= unit exp++ } return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp]) } func GetInternalIpAdders(addresses []string) (ipv4List []string, ipv6List []string) { for _, addr := range addresses { // it parse (0.0.0.0) not cidr ip, _, err := net2.ParseCIDR(addr) if err != nil { continue } if ip.To4() != nil { ipv4List = append(ipv4List, addr) } else if ip.To16() != nil { ipv6List = append(ipv6List, addr) } } return ipv4List, ipv6List } func MatchNetInterfaceRight(interfaceName string) bool { match, _ := regexp.MatchString(`^(eth|enp|wlan|ens|eno)\d+`, interfaceName) if match { return true } match, _ = regexp.MatchString(`^(lo)`, interfaceName) if match { return true } return match }