@@ -148,6 +148,9 @@ func main() {
148148 User : agent .user ,
149149 Timestamp : time .Now (),
150150 Checks : agent .runAllChecks (ctx ),
151+ OS : agent .osInfo (ctx ),
152+ Architecture : agent .architecture (ctx ),
153+ Version : agent .osVersion (ctx ),
151154 SystemUptime : agent .systemUptime (ctx ),
152155 CPULoad : agent .cpuLoad (ctx ),
153156 LoggedInUsers : agent .loggedInUsers (ctx ),
@@ -268,6 +271,9 @@ func (a *Agent) reportToServer(ctx context.Context) {
268271 User : a .user ,
269272 Timestamp : time .Now (),
270273 Checks : a .runAllChecks (ctx ),
274+ OS : a .osInfo (ctx ),
275+ Architecture : a .architecture (ctx ),
276+ Version : a .osVersion (ctx ),
271277 SystemUptime : uptime ,
272278 CPULoad : cpuLoad ,
273279 LoggedInUsers : loggedInUsers ,
@@ -576,6 +582,13 @@ func (*Agent) cpuLoad(ctx context.Context) string {
576582
577583 if output , err := cmd .Output (); err == nil {
578584 result := strings .TrimSpace (string (output ))
585+ // For Linux /proc/loadavg, extract just the three load averages
586+ if runtime .GOOS == "linux" {
587+ fields := strings .Fields (result )
588+ if len (fields ) >= 3 {
589+ result = strings .Join (fields [:3 ], " " )
590+ }
591+ }
579592 // For uptime output on Solaris, extract just the load average part
580593 if (runtime .GOOS == "solaris" || runtime .GOOS == "illumos" ) && strings .Contains (result , "load average:" ) {
581594 parts := strings .Split (result , "load average:" )
@@ -628,6 +641,77 @@ func (*Agent) loggedInUsers(ctx context.Context) string {
628641 return "unavailable"
629642}
630643
644+ func (* Agent ) osInfo (ctx context.Context ) string {
645+ ctx , cancel := context .WithTimeout (ctx , 5 * time .Second )
646+ defer cancel ()
647+ var cmd * exec.Cmd
648+ switch runtime .GOOS {
649+ case "linux" :
650+ // Try to get pretty name from os-release
651+ if data , err := os .ReadFile ("/etc/os-release" ); err == nil {
652+ lines := strings .Split (string (data ), "\n " )
653+ for _ , line := range lines {
654+ if strings .HasPrefix (line , "PRETTY_NAME=" ) {
655+ name := strings .TrimPrefix (line , "PRETTY_NAME=" )
656+ return strings .Trim (name , `"` )
657+ }
658+ }
659+ }
660+ // Fallback to uname
661+ cmd = exec .CommandContext (ctx , "uname" , "-s" )
662+ case "darwin" :
663+ cmd = exec .CommandContext (ctx , "sw_vers" , "-productName" )
664+ case "windows" :
665+ cmd = exec .CommandContext (ctx , "wmic" , "os" , "get" , "Caption" , "/value" )
666+ default :
667+ cmd = exec .CommandContext (ctx , "uname" , "-s" )
668+ }
669+ if cmd != nil {
670+ if output , err := cmd .Output (); err == nil {
671+ result := strings .TrimSpace (string (output ))
672+ if runtime .GOOS == "windows" && strings .Contains (result , "Caption=" ) {
673+ result = strings .TrimPrefix (result , "Caption=" )
674+ }
675+ if result != "" {
676+ return result
677+ }
678+ }
679+ }
680+ // Fallback to Go's runtime info
681+ return runtime .GOOS
682+ }
683+
684+ func (* Agent ) architecture (ctx context.Context ) string {
685+ // runtime.GOARCH is the most reliable way to get architecture
686+ return runtime .GOARCH
687+ }
688+
689+ func (* Agent ) osVersion (ctx context.Context ) string {
690+ ctx , cancel := context .WithTimeout (ctx , 5 * time .Second )
691+ defer cancel ()
692+ var cmd * exec.Cmd
693+ switch runtime .GOOS {
694+ case "linux" :
695+ cmd = exec .CommandContext (ctx , "uname" , "-r" )
696+ case "darwin" :
697+ cmd = exec .CommandContext (ctx , "sw_vers" , "-productVersion" )
698+ case "windows" :
699+ cmd = exec .CommandContext (ctx , "wmic" , "os" , "get" , "Version" , "/value" )
700+ default :
701+ cmd = exec .CommandContext (ctx , "uname" , "-r" )
702+ }
703+ if output , err := cmd .Output (); err == nil {
704+ result := strings .TrimSpace (string (output ))
705+ if runtime .GOOS == "windows" && strings .Contains (result , "Version=" ) {
706+ result = strings .TrimPrefix (result , "Version=" )
707+ }
708+ if result != "" {
709+ return result
710+ }
711+ }
712+ return "unknown"
713+ }
714+
631715func darwinHardwareID () string {
632716 ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
633717 defer cancel ()
0 commit comments