//go:build linux package processor import ( "bufio" "fmt" "log" "os" "regexp" "strconv" "strings" ) var numberRegex *regexp.Regexp = regexp.MustCompile(`\d+`) func getLinuxCpuInfo() (ProcessorInformation, error) { procFile, err := os.Open("/proc/stat") if err != nil { return ProcessorInformation{}, fmt.Errorf("Could not find /proc/stat. Are you sure you are on linux?") } defer procFile.Close() fileReader := bufio.NewScanner(procFile) var idleTime uint64 var nice uint64 var kernelTime uint64 var userTime uint64 var iowait uint64 var irq uint64 var softirq uint64 for linesExtracted := 0; fileReader.Scan(); linesExtracted++ { line := fileReader.Text() if strings.HasPrefix(line, "cpu ") { /* * fields[0] name of the core, we are extracting the first row so "total cpu", we don't care about subsequent cores (yet?) * fields[1] a useless space to skip * fields[2] cpu ticks spent on user processes * fields[3] cpu ticks spent on low priority processes * fields[4] cpu ticks spent on kernel processes * fields[5] idle time measured in cpu ticks * fields[6] cpu ticks spent on iowait (disk/network) * fields[7] irq (hardware interrupt) * fields[8] softirq (software interrupt) * fields[9] steal < for virtualization * fields[10] guest < for virtualization * fields[11] guest_nice < for virtualization */ fields := strings.Split(line, " ") userTime, _ = strconv.ParseUint(fields[2], 10, 64) nice, _ = strconv.ParseUint(fields[3], 10, 64) kernelTime, _ = strconv.ParseUint(fields[4], 10, 64) idleTime, _ = strconv.ParseUint(fields[5], 10, 64) iowait, _ = strconv.ParseUint(fields[6], 10, 64) // a type of idle time irq, _ = strconv.ParseUint(fields[7], 10, 64) // active time softirq, _ = strconv.ParseUint(fields[8], 10, 64) // active time } // ? Possibly extract more rows later on, for example breaking down each core and not just the combined value if linesExtracted >= 1 { break } } if fileReader.Err() != nil { return ProcessorInformation{}, fmt.Errorf("There was an error while reading /proc/stat. Error: %v", fileReader.Err()) } return ProcessorInformation{ IdleTimeSinceBoot: idleTime + iowait, KernelTimeSinceBoot: kernelTime + irq + softirq, UserTimeSinceBoot: userTime + nice, }, nil } func GetCPUInformation() ProcessorInformation { info, err := getLinuxCpuInfo() if err != nil { log.Printf("Could not read processor info. Error: %v", err) return ProcessorInformation{} } return info }