From 53f4f526cfa006b2ecd1c5e4504a8ac261e43790 Mon Sep 17 00:00:00 2001 From: zeaslity Date: Thu, 21 Dec 2023 11:39:19 +0800 Subject: [PATCH] [Agent] [Status] agent metric accomplish --- agent-go/rabbitmq/OctopusMessage.go | 2 +- agent-go/status/Disk.go | 64 ++++++++++++-- agent-go/status/Docker_test.go | 17 ++++ agent-go/status/Dokcer.go | 56 ++++++++++++ agent-go/status/Memory.go | 2 +- agent-go/status/Memory_test.go | 2 +- agent-go/status/Network_test.go | 6 +- agent-go/status/Status.go | 131 ++++++++++++++++++++++------ agent-go/status/Status_test.go | 15 ++-- 9 files changed, 246 insertions(+), 49 deletions(-) create mode 100644 agent-go/status/Docker_test.go create mode 100644 agent-go/status/Dokcer.go diff --git a/agent-go/rabbitmq/OctopusMessage.go b/agent-go/rabbitmq/OctopusMessage.go index 279b1cb..84acdff 100644 --- a/agent-go/rabbitmq/OctopusMessage.go +++ b/agent-go/rabbitmq/OctopusMessage.go @@ -174,7 +174,7 @@ func statusOMHandler(octopusMessage *OctopusMessage) { statusRes = status.Ping() } else if strings.HasPrefix(statusMessage.StatusType, "METRIC") { // metric info - agentStatusString, _ := json.Marshal(status.ReportAppStatus()) + agentStatusString, _ := json.Marshal(status.ReportAgentMetric()) statusRes = string(agentStatusString) } else if strings.HasPrefix(statusMessage.StatusType, "INFO") { diff --git a/agent-go/status/Disk.go b/agent-go/status/Disk.go index 6e24af0..4396918 100644 --- a/agent-go/status/Disk.go +++ b/agent-go/status/Disk.go @@ -1,9 +1,9 @@ package status import ( - "agent-go/utils" "fmt" "github.com/shirou/gopsutil/v3/disk" + "regexp" "time" ) @@ -14,7 +14,13 @@ type DiskStatus struct { } type DiskInfo struct { - DiskPartition []disk.PartitionStat + Device string `json:"device"` + Mountpoint string `json:"mountpoint"` + Fstype string `json:"fstype"` + Total uint64 `json:"total"` + Free uint64 `json:"free"` + Used uint64 `json:"used"` + UsedPercent float64 `json:"usedPercent"` } func GetDiskStatus() *DiskStatus { @@ -36,20 +42,43 @@ func GetDiskStatus() *DiskStatus { return ds } -func GetDiskInfo() (*DiskInfo, error) { +func GetDiskInfo() ([]DiskInfo, error) { - partitionStats, err := disk.Partitions(true) + partitionStats, err := disk.Partitions(false) if err != nil { log.ErrorF("[GetDiskInfo] - get disk partition info error ! => %v", err) return nil, err } - d := &DiskInfo{} + var result []DiskInfo + for _, partitionStat := range partitionStats { - utils.BeautifulPrint(partitionStat) + if !MatchNeededDisk(partitionStat.Device) { + continue + } + + usageStat, err := disk.Usage(partitionStat.Mountpoint) + if err != nil { + log.ErrorF("[GetDiskInfo] - device [%s] get mount point [%s] usage error => %v", partitionStat.Device, partitionStat.Mountpoint, err) + return nil, err + } + + // new disk info + diskInfo := DiskInfo{ + Device: partitionStat.Device, + Mountpoint: partitionStat.Mountpoint, + Fstype: partitionStat.Fstype, + Total: usageStat.Total, + Free: usageStat.Free, + Used: usageStat.Used, + UsedPercent: usageStat.UsedPercent, + } + + // assign + result = append(result, diskInfo) } - return d, nil + return result, nil } func CalculateDiskIO() { @@ -67,3 +96,24 @@ func CalculateDiskIO() { fmt.Printf("%v: read %vKB/s, write %vKB/s\n", device, readSpeed, writeSpeed) } } + +func MatchNeededDisk(deviceName string) bool { + match, _ := regexp.MatchString(`^(/dev/loop)\d+`, deviceName) + if match { + return false + } + //if strings.HasPrefix(deviceName, "/sys") { + // return false + //} + //if strings.HasPrefix(deviceName, "/run") { + // return false + //} + //if strings.HasPrefix(deviceName, "/snap") { + // return false + //} + //if strings.HasPrefix(deviceName, "tracefs") { + // return false + //} + + return true +} diff --git a/agent-go/status/Docker_test.go b/agent-go/status/Docker_test.go new file mode 100644 index 0000000..27087cd --- /dev/null +++ b/agent-go/status/Docker_test.go @@ -0,0 +1,17 @@ +package status + +import ( + "testing" +) + +func TestGetDockerInfo(t *testing.T) { + + GetDockerInfo() + //diskInfo, err := + //if err != nil { + // t.Errorf("get docker info error %v", err) + //} + // + //utils.BeautifulPrint(diskInfo) + +} diff --git a/agent-go/status/Dokcer.go b/agent-go/status/Dokcer.go new file mode 100644 index 0000000..7162511 --- /dev/null +++ b/agent-go/status/Dokcer.go @@ -0,0 +1,56 @@ +package status + +import ( + "agent-go/utils" + "github.com/shirou/gopsutil/v3/docker" + "strings" +) + +type DockerMetric struct { + DockerStats []docker.CgroupDockerStat +} + +func GetDockerMetric() (*DockerMetric, error) { + dockerStats, err := docker.GetDockerStat() + if err != nil { + log.ErrorF("[GetDockerMetric] - get docker stats list error %v", err) + return nil, err + } + + return &DockerMetric{ + DockerStats: dockerStats, + }, nil + +} + +func GetDockerInfo() { + + //dockerIDList, err := docker.GetDockerIDList() + //if err != nil { + // log.ErrorF("[GetDockerInfo] - get docker id list error %v", err) + //} + //utils.BeautifulPrint(dockerIDList) + + dockerStats, err := docker.GetDockerStat() + if err != nil { + log.ErrorF("[GetDockerInfo] - get docker stats list error %v", err) + } + + utils.BeautifulPrint(dockerStats) + + for _, dockerStat := range dockerStats { + if strings.Contains(dockerStat.Name, "mysql") { + cpuDocker, _ := docker.CgroupCPUDocker(dockerStat.ContainerID) + + utils.BeautifulPrint(cpuDocker) + + usageDocker, _ := docker.CgroupCPUUsageDocker(dockerStat.ContainerID) + utils.BeautifulPrint(usageDocker) + + mem, _ := docker.CgroupMemDocker(dockerStat.ContainerID) + utils.BeautifulPrint(mem) + + } + } + +} diff --git a/agent-go/status/Memory.go b/agent-go/status/Memory.go index f770e81..dfe3153 100644 --- a/agent-go/status/Memory.go +++ b/agent-go/status/Memory.go @@ -45,7 +45,7 @@ type MemoryInfo struct { HugePageSize uint64 `json:"hugePageSize"` } -func GetMemoryStatus() (*MemoryMetric, error) { +func GetMemoryMetric() (*MemoryMetric, error) { virtualMemoryStat, err := mem.VirtualMemory() if err != nil { return nil, err diff --git a/agent-go/status/Memory_test.go b/agent-go/status/Memory_test.go index 30024b3..b5c5575 100644 --- a/agent-go/status/Memory_test.go +++ b/agent-go/status/Memory_test.go @@ -8,7 +8,7 @@ import ( func TestGetMemoryStatus(t *testing.T) { - memoryStatus, err := GetMemoryStatus() + memoryStatus, err := GetMemoryMetric() if err != nil { return } diff --git a/agent-go/status/Network_test.go b/agent-go/status/Network_test.go index a365809..268641b 100644 --- a/agent-go/status/Network_test.go +++ b/agent-go/status/Network_test.go @@ -1,6 +1,7 @@ package status import ( + "agent-go/utils" "encoding/json" "fmt" "testing" @@ -37,10 +38,7 @@ func TestGetNetworkInfo(t *testing.T) { } for _, networkInfo := range networkInfos { - fmt.Println() - marshal, _ := json.MarshalIndent(networkInfo, "", " ") - fmt.Println(string(marshal)) - fmt.Println() + utils.BeautifulPrint(networkInfo) } } diff --git a/agent-go/status/Status.go b/agent-go/status/Status.go index 3dad063..17effd7 100644 --- a/agent-go/status/Status.go +++ b/agent-go/status/Status.go @@ -1,12 +1,14 @@ package status import ( + "agent-go/g" logger2 "agent-go/logger" "fmt" "time" ) var log = logger2.Log +var pool = g.G.P type StatusMessage struct { /** @@ -20,11 +22,107 @@ type StatusMessage struct { metricRepeatPinch int `json:"metricRepeatPinch,omitempty"` } -type AgentStatus struct { - CPUStatus *CPUMetric - MemoryStatus *MemoryMetric - NetworkStatus *NetworkStatus - DiskStatus *DiskStatus +type AgentMetric struct { + CPUMetric *CPUMetric + MemoryMetric *MemoryMetric + NetworkMetric []NetworkMetric + DiskInfo []DiskInfo + DockerMetric *DockerMetric +} + +func Ping() string { + return "PONG" +} + +func ReportAgentMetric() *AgentMetric { + + lenOfAgentMetric := 5 + waitResultChan := make(chan string, lenOfAgentMetric) + timeout := time.After(5 * time.Second) + var err error + + var cpuMetric *CPUMetric + err = pool.Submit(func() { + cpuMetric, err = GetCPUMetric() + if err != nil { + log.ErrorF("获取Agent的状态出现错误! 请检查 => %v", err) + waitResultChan <- "GetCPUMetric error !" + } + waitResultChan <- "GetCPUMetric success !" + }) + if err != nil { + log.ErrorF("[ReportAgentMetric] - GetCPUMetric exec error => %v", err) + } + + var memoryMetric *MemoryMetric + err = pool.Submit(func() { + memoryMetric, err = GetMemoryMetric() + if err != nil { + log.ErrorF("获取Agent的状态出现错误! 请检查 => %v", err) + waitResultChan <- "GetMemoryMetric error !" + } + waitResultChan <- "GetMemoryMetric success !" + }) + if err != nil { + log.ErrorF("[ReportAgentMetric] - GetMemoryMetric exec error => %v", err) + } + + var diskInfoList []DiskInfo + err = pool.Submit(func() { + diskInfoList, err = GetDiskInfo() + if err != nil { + log.ErrorF("获取Agent的状态出现错误! 请检查 => %v", err) + waitResultChan <- "GetDiskInfo error !" + } + waitResultChan <- "GetDiskInfo success !" + }) + if err != nil { + log.ErrorF("[ReportAgentMetric] - GetDiskInfo exec error => %v", err) + } + + var networkMetric []NetworkMetric + err = pool.Submit(func() { + networkMetric, err = GetNetworkMetric() + if err != nil { + log.ErrorF("获取Agent的状态出现错误! 请检查 => %v", err) + waitResultChan <- "GetNetworkMetric error !" + } + waitResultChan <- "GetNetworkMetric success !" + }) + if err != nil { + log.ErrorF("[ReportAgentMetric] - GetNetworkMetric exec error => %v", err) + } + var dockerMetric *DockerMetric + err = pool.Submit(func() { + dockerMetric, err = GetDockerMetric() + if err != nil { + log.ErrorF("获取Agent的状态出现错误! 请检查 => %v", err) + waitResultChan <- "GetDockerMetric error !" + } + waitResultChan <- "GetDockerMetric success !" + }) + if err != nil { + log.ErrorF("[ReportAgentMetric] - GetDockerMetric exec error => %v", err) + } + + for i := 0; i < lenOfAgentMetric; i++ { + select { + case result := <-waitResultChan: + log.DebugF("[ReportAgentMetric] - metric received => %s", result) + case <-timeout: + fmt.Println("[ReportAgentMetric] - Timeout! Not all results received.") + break + } + } + + return &AgentMetric{ + CPUMetric: cpuMetric, + MemoryMetric: memoryMetric, + NetworkMetric: networkMetric, + DiskInfo: diskInfoList, + DockerMetric: dockerMetric, + } + } func ConvertToFormat(eventData float64) string { @@ -38,26 +136,3 @@ func ConvertToFormat(eventData float64) string { milliseconds := duration.Milliseconds() % 1000 return fmt.Sprintf("%02d:%02d:%02d,%03d", hours, minutes, seconds, milliseconds) } - -func Ping() string { - return "PONG" -} - -func ReportAppStatus() *AgentStatus { - - cpuStatus, cpuerr := GetCPUMetric() - memoryStatus, memerr := GetMemoryStatus() - networkStatus, neterr := GetNetworkStatus() - if cpuerr != nil || memerr != nil || neterr != nil { - log.ErrorF("获取Agent的状态出现错误! 请检查") - return nil - } - diskStatus := GetDiskStatus() - return &AgentStatus{ - CPUStatus: cpuStatus, - MemoryStatus: memoryStatus, - NetworkStatus: networkStatus, - DiskStatus: diskStatus, - } - -} diff --git a/agent-go/status/Status_test.go b/agent-go/status/Status_test.go index 2ba647d..452f224 100644 --- a/agent-go/status/Status_test.go +++ b/agent-go/status/Status_test.go @@ -1,9 +1,10 @@ package status import ( - "encoding/json" + "agent-go/utils" "fmt" "testing" + "time" ) func TestConvertToFormat(t *testing.T) { @@ -15,12 +16,12 @@ func TestConvertToFormat(t *testing.T) { func TestReportAppStatus(t *testing.T) { - agentStatus := ReportAppStatus() + startTime := time.Now() + agentStatus := ReportAgentMetric() - marshal, err := json.Marshal(agentStatus) - if err != nil { - return - } + endTime := time.Now() + elapsedTime := endTime.Sub(startTime) + fmt.Println("函数执行时间:", elapsedTime) - fmt.Printf(string(marshal)) + utils.BeautifulPrint(agentStatus) }