//go:build windows // +build windows package main import ( "bytes" "encoding/json" "flag" "fmt" "io" "log" stdnet "net" "net/http" "os" "os/exec" "runtime" "sort" "strconv" "strings" "sync" "time" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/disk" "github.com/shirou/gopsutil/mem" "github.com/shirou/gopsutil/net" "github.com/shirou/gopsutil/process" "golang.org/x/text/encoding/simplifiedchinese" ) // 只在Windows平台下导入wmi包 // Config Agent配置 type Config struct { ServerURL string `json:"server_url"` ID string `json:"id"` // Agent唯一标识,自动生成 Name string `json:"name"` // Agent显示名称 Token string `json:"token"` // 设备认证令牌 Interval string `json:"interval"` // 采集间隔 Debug bool `json:"debug"` // 调试模式 APIPort int `json:"api_port"` // API端口 } // NetworkInterfaceMetrics 网卡监控指标 type NetworkInterfaceMetrics struct { BytesSent uint64 `json:"bytes_sent"` // 发送速率 (bytes/s) BytesReceived uint64 `json:"bytes_received"` // 接收速率 (bytes/s) TxBytes uint64 `json:"tx_bytes"` // 累计发送字节数 RxBytes uint64 `json:"rx_bytes"` // 累计接收字节数 } // DiskMetrics 磁盘监控指标 type DiskMetrics struct { UsedPercent float64 `json:"used_percent"` // 使用率百分比 Total uint64 `json:"total"` // 总容量 (bytes) } // ProcessMetrics 进程监控指标 type ProcessMetrics struct { Name string `json:"name"` // 进程名 Username string `json:"username"` // 用户名 PID int32 `json:"pid"` // 进程ID CPU float64 `json:"cpu"` // CPU使用率 Memory float64 `json:"memory"` // 内存使用率 Path string `json:"path"` // 路径 Cmdline string `json:"cmdline"` // 命令行 Ports []int `json:"ports"` // 占用端口 } // DiskDetailMetrics 磁盘详细信息 type DiskDetailMetrics struct { ID string `json:"id"` // 磁盘唯一ID(数字序列) Path string `json:"path"` // 设备路径 Status string `json:"status"` // 设备状态 Type string `json:"type"` // 设备类型 SizeGB float64 `json:"size_gb"` // 设备大小(GB) Model string `json:"model"` // 设备型号 Vendor string `json:"vendor"` // 设备厂商 InterfaceType string `json:"interface_type"` // 接口类型 FileSystem string `json:"file_system"` // 文件系统 DiskUUID string `json:"disk_uuid"` // 磁盘UUID Description string `json:"description"` // 设备描述 } // LogEntry 系统日志条目 type LogEntry struct { Sequence int `json:"sequence"` // 日志序号 Source string `json:"source"` // 来源 Time time.Time `json:"time"` // 发生时间 Message string `json:"message"` // 内容 } // OSInfo 操作系统信息 type OSInfo struct { Name string `json:"name"` // 操作系统名称 Version string `json:"version"` // 操作系统版本 Arch string `json:"arch"` // 系统架构 Fullname string `json:"fullname"` // 完整名称(Name+Version) } // CPUInfo CPU详细信息 type CPUInfo struct { Model string `json:"model"` // CPU型号 Cores int `json:"cores"` // 核心数 Threads int `json:"threads"` // 线程数 MaxFreq float64 `json:"max_freq"` // 最大频率 (MHz) MinFreq float64 `json:"min_freq"` // 最小频率 (MHz) AvgFreq float64 `json:"avg_freq"` // 平均频率 (MHz) Usage float64 `json:"usage"` // 当前使用率 } // MemoryInfo 内存详细信息 type MemoryInfo struct { Total uint64 `json:"total"` // 总容量 (bytes) Used uint64 `json:"used"` // 已使用 (bytes) Free uint64 `json:"free"` // 空闲 (bytes) UsedPercent float64 `json:"used_percent"` // 使用率百分比 } // NetworkHardwareInfo 网卡硬件信息 type NetworkHardwareInfo struct { ID string `json:"id"` // 网卡唯一ID(数字序列) Name string `json:"name"` // 网卡名称 MAC string `json:"mac"` // MAC地址 IPAddresses []string `json:"ip_addresses"` // IP地址列表 MTU int `json:"mtu"` // MTU值 Speed int `json:"speed"` // 网卡速度 (Mbps) Up bool `json:"up"` // 是否启用 } // HardwareMetrics 硬件信息指标 type HardwareMetrics struct { OS OSInfo `json:"os"` // 操作系统信息 CPU CPUInfo `json:"cpu"` // CPU信息 Memory MemoryInfo `json:"memory"` // 内存信息 DiskDetails []DiskDetailMetrics `json:"disk_details"` // 磁盘硬件信息 NetworkCards []NetworkHardwareInfo `json:"network_cards"` // 网卡硬件信息 } // Metrics 监控指标 type Metrics struct { CPU float64 `json:"cpu"` CPUHz float64 `json:"cpu_hz"` // CPU频率 (MHz) Memory float64 `json:"memory"` Disk map[string]DiskMetrics `json:"disk"` DiskDetails []DiskDetailMetrics `json:"disk_details"` // 磁盘详细信息 Network map[string]NetworkInterfaceMetrics `json:"network"` Processes []ProcessMetrics `json:"processes"` // 进程信息 Logs []LogEntry `json:"logs"` // 系统日志 RxTotal uint64 `json:"rx_total"` // 所有网卡累计接收字节数总和 TxTotal uint64 `json:"tx_total"` // 所有网卡累计发送字节数总和 RxRate uint64 `json:"rx_rate"` // 所有网卡实时接收速率总和 (bytes/s) TxRate uint64 `json:"tx_rate"` // 所有网卡实时发送速率总和 (bytes/s) // 设备信息字段 AgentID string `json:"agent_id"` // Agent唯一标识 Name string `json:"name"` // 设备名称 IP string `json:"ip"` // 设备IP地址 // 硬件信息 Hardware HardwareMetrics `json:"hardware"` // 硬件详细信息 } // 全局配置 var config Config // 保存解析后的时间间隔 var parsedInterval time.Duration // 命令行参数 var ( // 日志文件路径 logFile string ) // 保存上一次网络流量采集的数据 type NetworkStats struct { BytesSent uint64 BytesReceived uint64 } var ( lastNetworkStats = make(map[string]NetworkStats) lastCollectTime time.Time ) // 保存采集到的数据点 var metricsBuffer []*Metrics var metricsBufferMutex sync.Mutex // 初始化互斥锁 func init() { metricsBuffer = make([]*Metrics, 0) } // getLocalIP 获取本机IP地址 func getLocalIP() string { // 获取所有网络接口 interfaces, err := stdnet.Interfaces() if err != nil { log.Printf("Failed to get network interfaces: %v", err) return "" } // 遍历网络接口查找非回环、UP状态的IP for _, iface := range interfaces { // 跳过回环接口和非UP状态的接口 if iface.Flags&stdnet.FlagLoopback != 0 || iface.Flags&stdnet.FlagUp == 0 { continue } // 获取接口的IP地址 addresses, err := iface.Addrs() if err != nil { log.Printf("Failed to get addresses for interface %s: %v", iface.Name, err) continue } // 遍历地址并返回IPv4地址 for _, addr := range addresses { var ip stdnet.IP switch v := addr.(type) { case *stdnet.IPNet: ip = v.IP case *stdnet.IPAddr: ip = v.IP } // 跳过IPv6地址和回环地址 if ip == nil || ip.IsLoopback() || ip.To4() == nil { continue } return ip.String() } } // 如果找不到合适的IP,尝试另一种方法 conn, err := stdnet.Dial("udp", "8.8.8.8:80") if err != nil { log.Printf("Failed to dial UDP: %v", err) return "" } defer conn.Close() localAddr := conn.LocalAddr().(*stdnet.UDPAddr) return localAddr.IP.String() } // 初始化配置 func initConfig() { // 默认配置 config = Config{ ServerURL: "http://localhost:8080/api", ID: "", // 自动生成 Name: "", // 自动生成或从配置读取 Token: "", // 设备认证令牌,从配置或环境变量读取 Interval: "10s", Debug: false, // 默认非调试模式 APIPort: 8081, // 默认API端口8081 } // 读取配置文件 readConfigFile() // 从环境变量读取配置(优先级高于配置文件) loadFromEnv() // 生成或确保ID存在 ensureAgentID() // 确保名称存在 ensureAgentName() // 保存配置到文件(如果有修改) saveConfigFile() // 解析时间间隔 var err error parsedInterval, err = time.ParseDuration(config.Interval) if err != nil { log.Printf("Failed to parse interval: %v, using default 10s", err) parsedInterval = 10 * time.Second } // 打印配置信息 if config.Debug { log.Printf("Agent ID: %s, Name: %s, Debug: %v, API Port: %d", config.ID, config.Name, config.Debug, config.APIPort) } else { log.Printf("Agent ID: %s, Name: %s", config.ID, config.Name) } } // 从环境变量读取配置 func loadFromEnv() { if serverURL := os.Getenv("AGENT_SERVER_URL"); serverURL != "" { config.ServerURL = serverURL } if id := os.Getenv("AGENT_ID"); id != "" { config.ID = id } if name := os.Getenv("AGENT_NAME"); name != "" { config.Name = name } if token := os.Getenv("AGENT_TOKEN"); token != "" { config.Token = token } if intervalStr := os.Getenv("AGENT_INTERVAL"); intervalStr != "" { config.Interval = intervalStr } if debugStr := os.Getenv("AGENT_DEBUG"); debugStr != "" { debug, err := strconv.ParseBool(debugStr) if err == nil { config.Debug = debug } } if apiPortStr := os.Getenv("AGENT_API_PORT"); apiPortStr != "" { apiPort, err := strconv.Atoi(apiPortStr) if err == nil && apiPort > 0 { config.APIPort = apiPort } } } // 确保Agent ID存在,不存在则生成 func ensureAgentID() { if config.ID != "" { return } // 使用时间戳和进程ID生成唯一ID config.ID = fmt.Sprintf("agent-%d-%d", time.Now().UnixNano(), os.Getpid()) log.Printf("Generated new Agent ID: %s", config.ID) } // 确保Agent名称存在,不存在则生成 func ensureAgentName() { if config.Name != "" { return } // 尝试获取主机名作为默认名称 hostname, err := os.Hostname() if err != nil { // 如果获取主机名失败,使用ID的前8位作为默认名称 hostname = fmt.Sprintf("Agent-%s", config.ID[:8]) } config.Name = hostname log.Printf("Generated new Agent Name: %s", config.Name) } // 保存配置到文件 func saveConfigFile() { // 获取配置文件路径,默认./agent.json,可通过环境变量指定 configFile := os.Getenv("AGENT_CONFIG_FILE") if configFile == "" { configFile = "./agent.json" } // 将配置转换为JSON jsonData, err := json.MarshalIndent(config, "", " ") if err != nil { log.Printf("Failed to marshal config: %v", err) return } // 保存配置到文件 if err := os.WriteFile(configFile, jsonData, 0644); err != nil { log.Printf("Failed to save config to file: %v", err) return } log.Printf("Config saved to %s", configFile) } // 初始化日志配置 func initLogging() error { // 默认日志输出到标准输出 var output io.Writer = os.Stdout // 如果指定了日志文件,则输出到文件 if logFile != "" { // 处理日志文件路径 logFilePath := logFile // 创建日志文件 file, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { return fmt.Errorf("failed to open log file: %v", err) } output = file } // 配置日志输出格式 log.SetOutput(output) log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) return nil } // 读取配置文件 func readConfigFile() { // 获取配置文件路径,默认./agent.json,可通过环境变量指定 configFile := os.Getenv("AGENT_CONFIG_FILE") if configFile == "" { configFile = "./agent.json" } // 检查配置文件是否存在 if _, err := os.Stat(configFile); os.IsNotExist(err) { log.Printf("Config file %s not found, using default config", configFile) return } // 读取配置文件 content, err := os.ReadFile(configFile) if err != nil { log.Printf("Failed to read config file %s: %v, using default config", configFile, err) return } // 解析配置文件 var fileConfig Config if err := json.Unmarshal(content, &fileConfig); err != nil { log.Printf("Failed to parse config file %s: %v, using default config", configFile, err) return } // 合并配置:所有字段都从配置文件覆盖,除了空字符串 if fileConfig.ServerURL != "" { config.ServerURL = fileConfig.ServerURL } if fileConfig.ID != "" { config.ID = fileConfig.ID } if fileConfig.Name != "" { config.Name = fileConfig.Name } if fileConfig.Token != "" { config.Token = fileConfig.Token } if fileConfig.Interval != "" { config.Interval = fileConfig.Interval } // 对于bool类型,总是从配置文件覆盖 config.Debug = fileConfig.Debug // 对于int类型,如果配置文件中的值大于0,则使用配置文件中的值,否则使用默认值 if fileConfig.APIPort > 0 { config.APIPort = fileConfig.APIPort } log.Printf("Config loaded from %s", configFile) } // 采集CPU使用率和频率 func collectCPU() (float64, float64, error) { // 采集CPU使用率 percentages, err := cpu.Percent(0, false) if err != nil { return 0, 0, err } // Windows环境下CPU频率获取方式不同,暂时返回0 return percentages[0], 0, nil } // 采集内存使用率 func collectMemory() (float64, error) { vm, err := mem.VirtualMemory() if err != nil { return 0, err } return vm.UsedPercent, nil } // 采集磁盘使用率和总容量 func collectDisk() (map[string]DiskMetrics, error) { // 获取系统所有挂载点 partitions, err := disk.Partitions(false) if err != nil { return nil, err } // 初始化返回值 diskMetricsMap := make(map[string]DiskMetrics) // 遍历所有挂载点,采集磁盘使用率和总容量 for _, partition := range partitions { // 获取磁盘使用率 usage, err := disk.Usage(partition.Mountpoint) if err != nil { log.Printf("Failed to collect disk usage for %s: %v", partition.Mountpoint, err) continue } // 创建磁盘指标 diskMetrics := DiskMetrics{ UsedPercent: usage.UsedPercent, Total: usage.Total, } // 将指标添加到map中,使用挂载点作为键 diskMetricsMap[partition.Mountpoint] = diskMetrics } return diskMetricsMap, nil } // 采集磁盘详细信息 func collectDiskDetails() ([]DiskDetailMetrics, error) { // 获取系统所有挂载点 partitions, err := disk.Partitions(true) if err != nil { return nil, err } // 初始化返回值 diskDetails := make([]DiskDetailMetrics, 0) // 遍历所有挂载点,采集磁盘详细信息 for i, partition := range partitions { // 获取磁盘使用率 usage, err := disk.Usage(partition.Mountpoint) if err != nil { log.Printf("Failed to collect disk usage for %s: %v", partition.Mountpoint, err) continue } // 创建磁盘详细信息 diskDetail := DiskDetailMetrics{ ID: fmt.Sprintf("%d", i+1), Path: partition.Mountpoint, Status: "active", Type: "disk", SizeGB: float64(usage.Total) / (1024 * 1024 * 1024), Model: "", Vendor: "", InterfaceType: "", FileSystem: partition.Fstype, DiskUUID: "", Description: fmt.Sprintf("Disk partition %s", partition.Mountpoint), } // 将磁盘详细信息添加到切片中 diskDetails = append(diskDetails, diskDetail) } return diskDetails, nil } // 采集网络流量 func collectNetwork() (map[string]NetworkInterfaceMetrics, uint64, uint64, uint64, uint64, error) { // 获取当前时间 currentTime := time.Now() // 获取网络接口列表 interfaces, err := net.Interfaces() if err != nil { return nil, 0, 0, 0, 0, err } // 初始化返回值 networkMetrics := make(map[string]NetworkInterfaceMetrics) var rxTotal, txTotal, rxRate, txRate uint64 // 遍历所有网络接口,采集网络流量 for _, iface := range interfaces { // 跳过回环接口 if strings.Contains(strings.ToLower(iface.Name), "loopback") || strings.Contains(strings.ToLower(iface.Name), "lo") { continue } // 获取网络接口统计信息 stats, err := net.IOCounters(true) if err != nil { log.Printf("Failed to collect network stats for %s: %v", iface.Name, err) continue } // 查找当前接口的统计信息 var interfaceStats net.IOCountersStat found := false for _, stat := range stats { if stat.Name == iface.Name { interfaceStats = stat found = true break } } if !found { continue } // 计算时间差 timeDiff := currentTime.Sub(lastCollectTime) if timeDiff <= 0 { timeDiff = time.Second } // 获取上一次采集的数据 lastStats, exists := lastNetworkStats[iface.Name] // 计算发送和接收速率 var bytesSent, bytesReceived uint64 if exists { bytesSent = uint64(float64(interfaceStats.BytesSent-lastStats.BytesSent) / timeDiff.Seconds()) bytesReceived = uint64(float64(interfaceStats.BytesRecv-lastStats.BytesReceived) / timeDiff.Seconds()) } // 创建网络指标 interfaceMetrics := NetworkInterfaceMetrics{ BytesSent: bytesSent, BytesReceived: bytesReceived, TxBytes: interfaceStats.BytesSent, RxBytes: interfaceStats.BytesRecv, } // 将指标添加到map中 networkMetrics[iface.Name] = interfaceMetrics // 更新上一次采集的数据 lastNetworkStats[iface.Name] = NetworkStats{ BytesSent: interfaceStats.BytesSent, BytesReceived: interfaceStats.BytesRecv, } // 累加总流量 rxTotal += interfaceStats.BytesRecv txTotal += interfaceStats.BytesSent rxRate += bytesReceived txRate += bytesSent } // 更新上一次采集时间 lastCollectTime = currentTime return networkMetrics, rxTotal, txTotal, rxRate, txRate, nil } // 采集进程信息 func collectProcessMetrics() ([]ProcessMetrics, error) { // 获取所有进程 processes, err := process.Processes() if err != nil { return nil, err } // 初始化返回值 processMetrics := make([]ProcessMetrics, 0) // 遍历所有进程,采集进程信息 for _, p := range processes { // 获取进程名称 name, err := p.Name() if err != nil { continue } // 获取进程用户名 username, err := p.Username() if err != nil { username = "" } // 获取进程CPU使用率 cpu, err := p.CPUPercent() if err != nil { cpu = 0 } // 获取进程内存使用率 mem, err := p.MemoryPercent() if err != nil { mem = 0 } // 获取进程路径 path, err := p.Exe() if err != nil { path = "" } // 获取进程命令行 cmdline, err := p.Cmdline() if err != nil { cmdline = "" } // 获取进程占用的端口 connections, err := p.Connections() if err != nil { continue } // 提取端口号 ports := make([]int, 0) for _, conn := range connections { ports = append(ports, int(conn.Laddr.Port)) } // 去重并排序端口号 sort.Ints(ports) uniquePorts := make([]int, 0) prevPort := -1 for _, port := range ports { if port != prevPort { uniquePorts = append(uniquePorts, port) prevPort = port } } // 创建进程指标 pm := ProcessMetrics{ Name: name, Username: username, PID: p.Pid, CPU: cpu, Memory: float64(mem), Path: path, Cmdline: cmdline, Ports: uniquePorts, } // 将指标添加到切片中 processMetrics = append(processMetrics, pm) } return processMetrics, nil } // 采集系统日志 func collectLogs() ([]LogEntry, error) { // Windows系统日志采集需要特殊处理,这里返回空切片 return []LogEntry{}, nil } // 采集操作系统信息 func collectOSInfo() (OSInfo, error) { // 默认值 name := "Windows" version := "Unknown" arch := "Unknown" fullname := "Windows" // 先获取架构信息 if runtime.GOARCH == "amd64" { arch = "64-bit" } else if runtime.GOARCH == "386" { arch = "32-bit" } // 使用wmic命令获取详细的Windows版本信息(包括版本类型和版本号) cmd := exec.Command("cmd.exe", "/c", "wmic os get Caption, Version, OSArchitecture /format:list") output, err := cmd.Output() if err == nil { // 处理GBK编码输出 decodedOutput, err := simplifiedchinese.GBK.NewDecoder().Bytes(output) if err != nil { // 解码失败时使用原始字符串 decodedOutput = output } outputStr := string(decodedOutput) // 解析wmic命令输出 lines := strings.Split(outputStr, "\n") for _, line := range lines { line = strings.TrimSpace(line) if line == "" { continue } // 解析Caption(完整名称,例如:Microsoft Windows 10 Pro) if strings.HasPrefix(line, "Caption=") { fullname = strings.TrimPrefix(line, "Caption=") } // 解析Version(版本号,例如:10.0.19045) if strings.HasPrefix(line, "Version=") { version = strings.TrimPrefix(line, "Version=") } // 解析OSArchitecture(架构,例如:64-bit) if strings.HasPrefix(line, "OSArchitecture=") { arch = strings.TrimPrefix(line, "OSArchitecture=") } } } else { // 如果wmic命令失败,使用ver命令作为备选 cmd := exec.Command("cmd.exe", "/c", "ver") output, err := cmd.Output() if err == nil { // 处理GBK编码输出 decodedOutput, err := simplifiedchinese.GBK.NewDecoder().Bytes(output) if err != nil { // 解码失败时使用原始字符串 decodedOutput = output } outputStr := string(decodedOutput) // 提取版本号 versionStart := strings.Index(outputStr, "[Version ") if versionStart > 0 { versionStart += 9 versionEnd := strings.Index(outputStr[versionStart:], "]") if versionEnd > 0 { version = outputStr[versionStart : versionStart+versionEnd] } } // 构建完整名称 fullname = fmt.Sprintf("Windows %s", version) } } return OSInfo{ Name: name, Version: version, Arch: arch, Fullname: fullname, }, nil } // 采集CPU详细信息 func collectCPUInfo() (CPUInfo, error) { // 获取CPU信息 cpus, err := cpu.Info() if err != nil { return CPUInfo{}, err } // 获取CPU使用率 usage, err := cpu.Percent(0, false) if err != nil { usage = []float64{0} } // Windows环境下CPU信息 cpuInfo := CPUInfo{ Model: cpus[0].ModelName, Cores: int(cpus[0].Cores), Threads: 0, // Windows环境下可能不支持Threads字段 MaxFreq: 0, // Windows环境下频率获取方式不同 MinFreq: 0, AvgFreq: 0, Usage: usage[0], } return cpuInfo, nil } // 采集内存详细信息 func collectMemoryInfo() (MemoryInfo, error) { // 获取内存信息 mem, err := mem.VirtualMemory() if err != nil { return MemoryInfo{}, err } // 创建内存详细信息 return MemoryInfo{ Total: mem.Total, Used: mem.Used, Free: mem.Free, UsedPercent: mem.UsedPercent, }, nil } // 采集网卡硬件信息 func collectNetworkHardware() ([]NetworkHardwareInfo, error) { // 获取网络接口列表 interfaces, err := net.Interfaces() if err != nil { return nil, err } // 初始化返回值 networkCards := make([]NetworkHardwareInfo, 0) // 获取所有IP地址 allAddrs, err := stdnet.InterfaceAddrs() if err != nil { allAddrs = []stdnet.Addr{} } // 遍历所有网络接口,采集网卡硬件信息 for i, iface := range interfaces { // 跳过回环接口 if strings.Contains(strings.ToLower(iface.Name), "loopback") || strings.Contains(strings.ToLower(iface.Name), "lo") { continue } // 提取IP地址 ipAddresses := make([]string, 0) for _, addr := range allAddrs { if ipnet, ok := addr.(*stdnet.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { ipAddresses = append(ipAddresses, ipnet.IP.String()) } } } // 创建网卡硬件信息 networkCard := NetworkHardwareInfo{ ID: fmt.Sprintf("%d", i+1), Name: iface.Name, MAC: iface.HardwareAddr, IPAddresses: ipAddresses, MTU: iface.MTU, Speed: 0, // 在Windows上,net.Interface没有Speed字段 Up: true, // Windows环境下接口状态判断方式不同 } // 将网卡硬件信息添加到切片中 networkCards = append(networkCards, networkCard) } return networkCards, nil } // 采集指标 func collectMetrics() (*Metrics, error) { metrics := &Metrics{} // 初始化Network字段为非nil,避免空指针问题 metrics.Network = make(map[string]NetworkInterfaceMetrics) // 设置设备信息 metrics.AgentID = config.ID metrics.Name = config.Name // 尝试获取本机IP地址 metrics.IP = getLocalIP() // 采集CPU使用率和频率 cpuUsage, cpuHz, err := collectCPU() if err != nil { // CPU采集失败时使用0值 log.Printf("Failed to collect CPU metrics: %v, using 0 values", err) cpuUsage = 0 cpuHz = 0 } metrics.CPU = cpuUsage metrics.CPUHz = cpuHz // 采集内存使用率 memoryUsage, err := collectMemory() if err != nil { // 内存采集失败时使用0值 log.Printf("Failed to collect memory metrics: %v, using 0 value", err) memoryUsage = 0 } metrics.Memory = memoryUsage // 采集磁盘使用率和总容量 diskMetricsMap, err := collectDisk() if err != nil { // 磁盘采集失败时使用空map log.Printf("Failed to collect disk metrics: %v, using empty map", err) diskMetricsMap = make(map[string]DiskMetrics) } metrics.Disk = diskMetricsMap // 采集磁盘详细信息 diskDetails, err := collectDiskDetails() if err != nil { // 磁盘详细信息采集失败时使用空切片 log.Printf("Failed to collect disk details: %v, using empty slice", err) diskDetails = make([]DiskDetailMetrics, 0) } metrics.DiskDetails = diskDetails // 采集进程信息 processes, err := collectProcessMetrics() if err != nil { // 进程信息采集失败时使用空切片 log.Printf("Failed to collect process metrics: %v, using empty slice", err) processes = make([]ProcessMetrics, 0) } metrics.Processes = processes // 采集网络流量 networkMetrics, rxTotal, txTotal, rxRate, txRate, err := collectNetwork() if err != nil { // 网络采集失败时使用0值 log.Printf("Failed to collect network metrics: %v, using 0 values", err) networkMetrics = make(map[string]NetworkInterfaceMetrics) rxTotal, txTotal, rxRate, txRate = 0, 0, 0, 0 } // 直接使用采集到的网卡流量 metrics.Network = networkMetrics metrics.RxTotal = rxTotal metrics.TxTotal = txTotal metrics.RxRate = rxRate metrics.TxRate = txRate // 采集系统日志 logs, err := collectLogs() if err != nil { // 日志采集失败时使用空切片 log.Printf("Failed to collect logs: %v, using empty slice", err) logs = make([]LogEntry, 0) } metrics.Logs = logs // 采集硬件信息 // 采集操作系统信息 osInfo, err := collectOSInfo() if err != nil { log.Printf("Failed to collect OS info: %v", err) } // 采集CPU详细信息 cpuInfo, err := collectCPUInfo() if err != nil { log.Printf("Failed to collect CPU info: %v", err) } // 采集内存详细信息 memoryInfo, err := collectMemoryInfo() if err != nil { log.Printf("Failed to collect memory info: %v", err) } // 采集网卡硬件信息 networkCards, err := collectNetworkHardware() if err != nil { log.Printf("Failed to collect network hardware info: %v", err) networkCards = make([]NetworkHardwareInfo, 0) } // 设置硬件信息 metrics.Hardware = HardwareMetrics{ OS: osInfo, CPU: cpuInfo, Memory: memoryInfo, DiskDetails: diskDetails, NetworkCards: networkCards, } return metrics, nil } // 发送指标到服务器 func sendMetrics(metricsList []*Metrics) error { // 创建HTTP客户端 client := &http.Client{ Timeout: 10 * time.Second, } // 将指标转换为JSON jsonData, err := json.Marshal(metricsList) if err != nil { return err } // 创建请求 req, err := http.NewRequest("POST", fmt.Sprintf("%s/metrics/", config.ServerURL), bytes.NewBuffer(jsonData)) if err != nil { return err } // 设置请求头 req.Header.Set("Content-Type", "application/json") // 设置Agent名称 req.Header.Set("X-Agent-Name", config.Name) // 设置设备认证令牌 req.Header.Set("X-Device-Token", config.Token) log.Printf("Sending %d metrics to server: %s", len(metricsList), config.ServerURL) // 发送请求 resp, err := client.Do(req) if err != nil { log.Printf("Failed to send metrics: %v", err) return err } defer resp.Body.Close() // 检查响应状态码 if resp.StatusCode != http.StatusOK { log.Printf("Server returned status code %d", resp.StatusCode) return fmt.Errorf("server returned status code %d", resp.StatusCode) } log.Printf("Successfully sent %d metrics to server", len(metricsList)) return nil } // 启动HTTP服务器 func startHTTPServer() { // 指标查询端点 http.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) { if config.Debug { log.Printf("API Request: %s %s", r.Method, r.URL.Path) } metrics, err := collectMetrics() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // 设置响应头 w.Header().Set("Content-Type", "application/json") // 返回JSON响应 json.NewEncoder(w).Encode(metrics) }) // 健康检查端点 http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { if config.Debug { log.Printf("API Request: %s %s", r.Method, r.URL.Path) } w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{ "status": "ok", "agent_id": config.ID, }) }) // 获取配置端点 http.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) { if config.Debug { log.Printf("API Request: %s %s", r.Method, r.URL.Path) } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(config) }) // 获取状态端点 http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) { if config.Debug { log.Printf("API Request: %s %s", r.Method, r.URL.Path) } // 采集当前状态 cpu, cpuHz, _ := collectCPU() memory, _ := collectMemory() disk, _ := collectDisk() status := map[string]interface{}{ "status": "running", "agent_id": config.ID, "name": config.Name, "debug": config.Debug, "interval": config.Interval, "cpu": cpu, "cpu_hz": cpuHz, "memory": memory, "disk": disk, } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(status) }) // 立即采集和发送指标端点 http.HandleFunc("/collect", func(w http.ResponseWriter, r *http.Request) { if config.Debug { log.Printf("API Request: %s %s", r.Method, r.URL.Path) } go collectAndSendMetrics() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{ "status": "ok", "message": "Metrics collection triggered", }) }) // 启动服务器 addr := fmt.Sprintf(":%d", config.APIPort) log.Printf("Starting HTTP server on %s", addr) if err := http.ListenAndServe(addr, nil); err != nil { log.Fatalf("Failed to start HTTP server: %v", err) } } // 采集并发送指标 func collectAndSendMetrics() { // 采集指标 metrics, err := collectMetrics() if err != nil { log.Printf("Failed to collect metrics: %v", err) return } // 将指标添加到缓冲区 metricsBufferMutex.Lock() metricsBuffer = append(metricsBuffer, metrics) metricsBufferMutex.Unlock() // 如果缓冲区已满,发送指标到服务器 metricsBufferMutex.Lock() if len(metricsBuffer) >= 10 { // 复制缓冲区 sendMetricsList := make([]*Metrics, len(metricsBuffer)) copy(sendMetricsList, metricsBuffer) // 清空缓冲区 metricsBuffer = make([]*Metrics, 0) metricsBufferMutex.Unlock() // 发送指标 if err := sendMetrics(sendMetricsList); err != nil { log.Printf("Failed to send metrics: %v", err) } } else { metricsBufferMutex.Unlock() } } func main() { // 解析命令行参数 flag.StringVar(&logFile, "log-file", "", "Path to log file") flag.StringVar(&logFile, "l", "", "Path to log file - shorthand") flag.Parse() // 初始化日志 if err := initLogging(); err != nil { log.Fatalf("Failed to initialize logging: %v", err) } // 初始化配置 initConfig() // 启动HTTP服务器 go startHTTPServer() // 采集初始指标 collectAndSendMetrics() // 创建定时器,定期采集指标 ticker := time.NewTicker(parsedInterval) defer ticker.Stop() // 主循环 log.Printf("Agent started successfully, collecting metrics every %s", config.Interval) for { select { case <-ticker.C: // 定期采集指标 collectAndSendMetrics() } } }