package main import ( "fmt" "log" "net" "os" "os/signal" "runtime" "syscall" "time" "pc-monitor-client/collector" "pc-monitor-client/reporter" ) func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) log.Println("PC Monitor Client starting...") // Load config cfg, err := LoadConfig("config.yaml") if err != nil { log.Fatalf("Failed to load config: %v", err) } // Get hostname and IP hostname, _ := os.Hostname() ip := getLocalIP() // Create reporter r := reporter.NewReporter(cfg.Server.URL, cfg.Server.Token) // Register device log.Printf("Registering device: %s (%s)", hostname, ip) deviceID, err := r.Register(hostname, runtime.GOOS, ip) if err != nil { log.Printf("Warning: Failed to register: %v", err) log.Println("Will retry on next report...") } else { log.Printf("Device registered with ID: %s", deviceID) } // Create ticker for collection collectTicker := time.NewTicker(cfg.Collect.Interval) defer collectTicker.Stop() reportTicker := time.NewTicker(cfg.Report.Interval) defer reportTicker.Stop() // Create channel for graceful shutdown sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) // Last collected metrics var lastMetrics *collector.Metrics log.Printf("Collecting metrics every %v", cfg.Collect.Interval) log.Printf("Reporting metrics every %v", cfg.Report.Interval) for { select { case <-collectTicker.C: metrics, err := collector.CollectAll() if err != nil { log.Printf("Error collecting metrics: %v", err) continue } metrics.DeviceID = deviceID lastMetrics = metrics log.Printf("Metrics collected: CPU=%.1f%%, Memory=%.1f%%", metrics.CPU.Usage, metrics.Memory.Usage) case <-reportTicker.C: if lastMetrics == nil { log.Println("No metrics to report yet") continue } if deviceID == "" { // Try to register again deviceID, err = r.Register(hostname, runtime.GOOS, ip) if err != nil { log.Printf("Failed to register: %v", err) continue } log.Printf("Device registered with ID: %s", deviceID) } if err := r.Report(lastMetrics); err != nil { log.Printf("Error reporting metrics: %v", err) } else { log.Println("Metrics reported successfully") } // Send heartbeat if err := r.Heartbeat(deviceID); err != nil { log.Printf("Error sending heartbeat: %v", err) } case <-sigChan: log.Println("Shutting down...") return } } } func getLocalIP() string { addrs, err := net.InterfaceAddrs() if err != nil { return "unknown" } for _, addr := range addrs { if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { if ipNet.IP.To4() != nil { return ipNet.IP.String() } } } return "unknown" }