cpu.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package usageinfo
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "strconv"
  6. "strings"
  7. "time"
  8. )
  9. type CPUStats struct {
  10. user uint64
  11. nice uint64
  12. system uint64
  13. idle uint64
  14. iowait uint64
  15. irq uint64
  16. softirq uint64
  17. }
  18. // getCPUStats reads and parses the CPU stats from /proc/stat
  19. func getCPUStats() (CPUStats, error) {
  20. data, err := ioutil.ReadFile("/proc/stat")
  21. if err != nil {
  22. return CPUStats{}, err
  23. }
  24. lines := strings.Split(string(data), "\n")
  25. for _, line := range lines {
  26. if strings.HasPrefix(line, "cpu ") {
  27. fields := strings.Fields(line)
  28. if len(fields) < 8 {
  29. return CPUStats{}, fmt.Errorf("unexpected format in /proc/stat")
  30. }
  31. // Parse the CPU fields into the CPUStats struct
  32. user, _ := strconv.ParseUint(fields[1], 10, 64)
  33. nice, _ := strconv.ParseUint(fields[2], 10, 64)
  34. system, _ := strconv.ParseUint(fields[3], 10, 64)
  35. idle, _ := strconv.ParseUint(fields[4], 10, 64)
  36. iowait, _ := strconv.ParseUint(fields[5], 10, 64)
  37. irq, _ := strconv.ParseUint(fields[6], 10, 64)
  38. softirq, _ := strconv.ParseUint(fields[7], 10, 64)
  39. return CPUStats{
  40. user: user,
  41. nice: nice,
  42. system: system,
  43. idle: idle,
  44. iowait: iowait,
  45. irq: irq,
  46. softirq: softirq,
  47. }, nil
  48. }
  49. }
  50. return CPUStats{}, fmt.Errorf("could not find CPU stats")
  51. }
  52. // calculateCPUUsage calculates the percentage of CPU usage
  53. func calculateCPUUsage(prev, current CPUStats) float64 {
  54. prevTotal := prev.user + prev.nice + prev.system + prev.idle + prev.iowait + prev.irq + prev.softirq
  55. currentTotal := current.user + current.nice + current.system + current.idle + current.iowait + current.irq + current.softirq
  56. totalDiff := currentTotal - prevTotal
  57. idleDiff := current.idle - prev.idle
  58. if totalDiff == 0 {
  59. return 0.0
  60. }
  61. usage := (float64(totalDiff-idleDiff) / float64(totalDiff)) * 100.0
  62. return usage
  63. }
  64. // GetCPUUsage returns the current CPU usage as a percentage
  65. // Note this is blocking and will sleep for 1 second
  66. func GetCPUUsageUsingProcStat() (float64, error) {
  67. // Get initial CPU stats
  68. prevStats, err := getCPUStats()
  69. if err != nil {
  70. return 0, err
  71. }
  72. // Sleep for 1 second to compare stats over time
  73. time.Sleep(1 * time.Second)
  74. // Get current CPU stats after 1 second
  75. currentStats, err := getCPUStats()
  76. if err != nil {
  77. return 0, err
  78. }
  79. // Calculate and print the CPU usage
  80. cpuUsage := calculateCPUUsage(prevStats, currentStats)
  81. return cpuUsage, nil
  82. }