package analytic import ( "encoding/json" "errors" "io" "net/http" "net/url" "sync" "time" "github.com/0xJacky/Nginx-UI/internal/transport" "github.com/0xJacky/Nginx-UI/internal/version" "github.com/0xJacky/Nginx-UI/model" "github.com/shirou/gopsutil/v4/load" "github.com/shirou/gopsutil/v4/net" "github.com/uozi-tech/cosy/logger" ) type NodeInfo struct { NodeRuntimeInfo version.RuntimeInfo `json:"node_runtime_info"` Version string `json:"version"` CPUNum int `json:"cpu_num"` MemoryTotal string `json:"memory_total"` DiskTotal string `json:"disk_total"` } type NodeStat struct { AvgLoad *load.AvgStat `json:"avg_load"` CPUPercent float64 `json:"cpu_percent"` MemoryPercent float64 `json:"memory_percent"` DiskPercent float64 `json:"disk_percent"` Network net.IOCountersStat `json:"network"` Status bool `json:"status"` ResponseAt time.Time `json:"response_at"` } type Node struct { EnvironmentID int `json:"environment_id,omitempty"` *model.Environment NodeStat NodeInfo } var mutex sync.Mutex type TNodeMap map[uint64]*Node var NodeMap TNodeMap func init() { NodeMap = make(TNodeMap) } func GetNode(env *model.Environment) (n *Node) { if env == nil { // this should never happen logger.Error("env is nil") return } if !env.Enabled { return &Node{ Environment: env, } } n, ok := NodeMap[env.ID] if !ok { n = &Node{} } n.Environment = env return n } func InitNode(env *model.Environment) (n *Node, err error) { n = &Node{ Environment: env, } u, err := url.JoinPath(env.URL, "/api/node") if err != nil { return } t, err := transport.NewTransport() if err != nil { return } client := http.Client{ Transport: t, } req, err := http.NewRequest("GET", u, nil) if err != nil { return } req.Header.Set("X-Node-Secret", env.Token) resp, err := client.Do(req) if err != nil { return } defer resp.Body.Close() bytes, _ := io.ReadAll(resp.Body) if resp.StatusCode != http.StatusOK { return n, errors.New(string(bytes)) } err = json.Unmarshal(bytes, &n.NodeInfo) if err != nil { return } return }