package collector import ( "net" "strings" "time" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/host" "github.com/shirou/gopsutil/v3/mem" psnet "github.com/shirou/gopsutil/v3/net" ) type Metrics struct { CPUPercent float64 MemoryPercent float64 MemoryTotal uint64 MemoryAvailable uint64 Disks []DiskInfo Networks []NetInfo UptimeSeconds float64 } type DiskInfo struct { MountPoint string Total uint64 Free uint64 Filesystem string } type NetInfo struct { Name string IPAddress string MAC string BytesSent uint64 BytesRecv uint64 } func Collect() (*Metrics, error) { cpuPercent, err := cpu.Percent(time.Second, false) if err != nil { return nil, err } memInfo, err := mem.VirtualMemory() if err != nil { return nil, err } uptime, _ := host.Uptime() m := &Metrics{ CPUPercent: cpuPercent[0], MemoryPercent: memInfo.UsedPercent, MemoryTotal: memInfo.Total, MemoryAvailable: memInfo.Available, UptimeSeconds: float64(uptime), } // Disks partitions, _ := disk.Partitions(false) for _, p := range partitions { usage, err := disk.Usage(p.Mountpoint) if err != nil { continue } m.Disks = append(m.Disks, DiskInfo{ MountPoint: p.Mountpoint, Total: usage.Total, Free: usage.Free, Filesystem: p.Fstype, }) } // Network interfaces, _ := psnet.Interfaces() counters, _ := psnet.IOCounters(true) counterMap := make(map[string]psnet.IOCountersStat) for _, c := range counters { counterMap[c.Name] = c } for _, iface := range interfaces { if len(iface.Addrs) == 0 || iface.HardwareAddr == "" { continue } // Loopback und virtuelle Adapter überspringen nameLower := strings.ToLower(iface.Name) if strings.Contains(nameLower, "loopback") || strings.Contains(nameLower, "teredo") || strings.Contains(nameLower, "isatap") || strings.Contains(nameLower, "6to4") { continue } ni := NetInfo{ Name: iface.Name, MAC: iface.HardwareAddr, } // IPv4 bevorzugen, IPv6 als Fallback for _, addr := range iface.Addrs { ip, _, err := net.ParseCIDR(addr.Addr) if err != nil { // Versuche direkte IP-Adresse (ohne CIDR) ip = net.ParseIP(addr.Addr) } if ip == nil || ip.IsLoopback() || ip.IsLinkLocalUnicast() { continue } if ip.To4() != nil { // IPv4 gefunden — nehmen und abbrechen ni.IPAddress = addr.Addr break } if ni.IPAddress == "" { // IPv6 als vorläufiger Fallback ni.IPAddress = addr.Addr } } if ni.IPAddress == "" { continue } if c, ok := counterMap[iface.Name]; ok { ni.BytesSent = c.BytesSent ni.BytesRecv = c.BytesRecv } m.Networks = append(m.Networks, ni) } return m, nil }