usageinfo.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. package usageinfo
  2. import (
  3. "math"
  4. "os/exec"
  5. "runtime"
  6. "strconv"
  7. "strings"
  8. )
  9. /*
  10. Usage Info (CPU / RAM)
  11. author: tobychui
  12. This module get the CPU information on different platform using
  13. native terminal commands
  14. */
  15. const query_cpuproc_command = "ps -eo pcpu,pid,user,args | sort -k 1 -r | head -10"
  16. const query_freemem_command = "top -d1 | sed '4q;d' | awk '{print $(NF-1)}'"
  17. const query_phymem_command = "sysctl hw.physmem | awk '{print $NF}'"
  18. //Get CPU Usage in percentage
  19. func GetCPUUsage() float64 {
  20. usage := float64(0)
  21. if runtime.GOOS == "windows" {
  22. cmd := exec.Command("system/hardware/windows/getCPUload.exe")
  23. out, err := cmd.CombinedOutput()
  24. if err != nil {
  25. usage = 0
  26. }
  27. percentageOnly := strings.Split(string(out), " ")[0]
  28. s, err := strconv.ParseFloat(percentageOnly, 64)
  29. if err != nil {
  30. usage = 0
  31. }
  32. usage = s
  33. } else if runtime.GOOS == "linux" || runtime.GOOS == "freebsd" {
  34. //Get CPU first 10 processes uses most CPU resources
  35. cmd := exec.Command("bash", "-c", query_cpuproc_command)
  36. out, err := cmd.CombinedOutput()
  37. if err != nil {
  38. usage = 0
  39. }
  40. usageCounter := float64(0)
  41. usageInfo := strings.Split(string(out), "\n")
  42. for _, info := range usageInfo {
  43. if strings.Contains(info, "%CPU") == false {
  44. dataChunk := strings.Split(strings.TrimSpace(info), " ")
  45. if len(dataChunk) > 0 {
  46. s, err := strconv.ParseFloat(dataChunk[0], 64)
  47. if err == nil {
  48. usageCounter += s
  49. }
  50. }
  51. }
  52. }
  53. // Prepare queryNCPUCommnad for core count query
  54. queryNCPUCommand := ""
  55. if runtime.GOOS == "linux" {
  56. queryNCPUCommand = "nproc"
  57. } else if runtime.GOOS == "freebsd" {
  58. queryNCPUCommand = "sysctl hw.ncpu | awk '{print $NF}'"
  59. }
  60. // Get CPU core count
  61. cmd = exec.Command(queryNCPUCommand)
  62. out, err = cmd.CombinedOutput()
  63. if err != nil {
  64. return usageCounter
  65. }
  66. // Divide total CPU usage by processes by total CPU core count
  67. coreCount, err := strconv.Atoi(string(out))
  68. if err != nil {
  69. coreCount = 1
  70. }
  71. usage = usageCounter / float64(coreCount)
  72. if usage > float64(100) {
  73. usage = 100
  74. }
  75. } else {
  76. // CPU Usage Not supported on this platform
  77. }
  78. return usage
  79. }
  80. //Get RAM Usage in Numeric values
  81. func GetNumericRAMUsage() (int64, int64) {
  82. usedRam := int64(-1)
  83. totalRam := int64(-1)
  84. if runtime.GOOS == "windows" {
  85. cmd := exec.Command("system/hardware/windows/RAMUsage.exe")
  86. out, err := cmd.CombinedOutput()
  87. if err != nil {
  88. return -1, -1
  89. }
  90. raminfo := strings.Split(strings.TrimSpace(string(out)), ",")
  91. if len(raminfo) == 3 {
  92. //The returned value is something like this
  93. //7639 MB,16315 MB,0.468219429972418
  94. tmp := strings.Split(raminfo[0], " ")[0]
  95. used, err := strconv.ParseInt(tmp, 10, 64)
  96. if err != nil {
  97. return -1, -1
  98. }
  99. tmp = strings.Split(raminfo[1], " ")[0]
  100. total, err := strconv.ParseInt(tmp, 10, 64)
  101. if err != nil {
  102. return -1, -1
  103. }
  104. usedRam = used * 1024 * 1024 //From MB to Bytes
  105. totalRam = total * 1024 * 1024 //From MB to Bytes
  106. return usedRam, totalRam
  107. } else {
  108. return -1, -1
  109. }
  110. } else if runtime.GOOS == "linux" {
  111. cmd := exec.Command("bash", "-c", "free -m | grep Mem:")
  112. out, err := cmd.CombinedOutput()
  113. if err != nil {
  114. return usedRam, totalRam
  115. }
  116. //If the output contain more than one Memory info, only use the first one
  117. if strings.Contains(string(out), "\n") {
  118. out = []byte(strings.Split(string(out), "\n")[0])
  119. }
  120. //Trim of double space to space
  121. for strings.Contains(string(out), " ") {
  122. out = []byte(strings.ReplaceAll(string(out), " ", " "))
  123. }
  124. data := strings.Split(string(out), " ")
  125. if len(data) > 3 {
  126. used, err := strconv.ParseInt(data[2], 10, 64)
  127. if err != nil {
  128. return -1, -1
  129. }
  130. total, err := strconv.ParseInt(data[1], 10, 64)
  131. if err != nil {
  132. return -1, -1
  133. }
  134. usedRam = used * 1024 * 1024
  135. totalRam = total * 1024 * 1024
  136. return usedRam, totalRam
  137. }
  138. } else if runtime.GOOS == "freebsd" {
  139. // Get usused memory size (free)
  140. cmd := exec.Command("bash", "-c", query_freemem_command)
  141. freeMemByteArr, err := cmd.CombinedOutput()
  142. if err != nil {
  143. return usedRam, totalRam
  144. }
  145. freeMemStr := string(freeMemByteArr)
  146. freeMemStr = strings.ReplaceAll(freeMemStr, "\n", "")
  147. freeMemSize, err := strconv.ParseFloat(strings.ReplaceAll(string(freeMemStr), "M", ""), 10)
  148. // Get phy memory size
  149. cmd = exec.Command("bash", "-c", query_phymem_command)
  150. phyMemByteArr, err := cmd.CombinedOutput()
  151. if err != nil {
  152. return usedRam, totalRam
  153. }
  154. phyMemStr := string(phyMemByteArr)
  155. phyMemStr = strings.ReplaceAll(phyMemStr, "\n", "")
  156. // phyMemSize in MB
  157. phyMemSizeFloat, err := strconv.ParseFloat(phyMemStr, 10)
  158. phyMemSizeFloat = math.Floor(phyMemSizeFloat)
  159. total := phyMemSizeFloat
  160. // Used memory
  161. usedRAMSizeFloat := phyMemSizeFloat - freeMemSize
  162. usedRAMSizeFloat = math.Floor(usedRAMSizeFloat)
  163. used := usedRAMSizeFloat
  164. totalRam = int64(total)
  165. usedRam = int64(used)
  166. return usedRam, totalRam
  167. }
  168. return -1, -1
  169. }
  170. //Get RAM usage, return used / total / used percentage
  171. func GetRAMUsage() (string, string, float64) {
  172. usedRam := "Unknown"
  173. totalRam := "Unknown"
  174. usedPercentage := float64(0)
  175. if runtime.GOOS == "windows" {
  176. cmd := exec.Command("system/hardware/windows/RAMUsage.exe")
  177. out, err := cmd.CombinedOutput()
  178. if err != nil {
  179. return usedRam, totalRam, usedPercentage
  180. }
  181. raminfo := strings.Split(strings.TrimSpace(string(out)), ",")
  182. if len(raminfo) == 3 {
  183. usedRam = raminfo[0]
  184. totalRam = raminfo[1]
  185. s, err := strconv.ParseFloat(raminfo[2], 64)
  186. if err != nil {
  187. return usedRam, totalRam, usedPercentage
  188. }
  189. usedPercentage = s * float64(100)
  190. } else {
  191. return usedRam, totalRam, usedPercentage
  192. }
  193. return usedRam, totalRam, usedPercentage
  194. } else if runtime.GOOS == "linux" {
  195. cmd := exec.Command("bash", "-c", "free -m | grep Mem:")
  196. out, err := cmd.CombinedOutput()
  197. if err != nil {
  198. return usedRam, totalRam, usedPercentage
  199. }
  200. //If the output contain more than one Memory info, only use the first one
  201. if strings.Contains(string(out), "\n") {
  202. out = []byte(strings.Split(string(out), "\n")[0])
  203. }
  204. //Trim of double space to space
  205. for strings.Contains(string(out), " ") {
  206. out = []byte(strings.ReplaceAll(string(out), " ", " "))
  207. }
  208. data := strings.Split(string(out), " ")
  209. if len(data) > 3 {
  210. usedRam = data[2] + " MB"
  211. totalRam = data[1] + " MB"
  212. //Calculate used memory
  213. usedFloat, err := strconv.ParseFloat(data[2], 64)
  214. if err != nil {
  215. return usedRam, totalRam, usedPercentage
  216. }
  217. totalFloat, err := strconv.ParseFloat(data[1], 64)
  218. if err != nil {
  219. return usedRam, totalRam, usedPercentage
  220. }
  221. usedPercentage = usedFloat / totalFloat * 100
  222. return usedRam, totalRam, usedPercentage
  223. }
  224. } else if runtime.GOOS == "freebsd" {
  225. // Get usused memory size (free)
  226. cmd := exec.Command("bash", "-c", query_freemem_command)
  227. freeMemByteArr, err := cmd.CombinedOutput()
  228. if err != nil {
  229. return usedRam, totalRam, usedPercentage
  230. }
  231. freeMemStr := string(freeMemByteArr)
  232. freeMemStr = strings.ReplaceAll(freeMemStr, "\n", "")
  233. freeMemSize, err := strconv.ParseFloat(strings.ReplaceAll(string(freeMemStr), "M", ""), 10)
  234. // Get phy memory size
  235. cmd = exec.Command("bash", "-c", query_phymem_command)
  236. phyMemByteArr, err := cmd.CombinedOutput()
  237. if err != nil {
  238. return usedRam, totalRam, usedPercentage
  239. }
  240. phyMemStr := string(phyMemByteArr)
  241. phyMemStr = strings.ReplaceAll(phyMemStr, "\n", "")
  242. // phyMemSize in MB
  243. phyMemSizeFloat, err := strconv.ParseFloat(phyMemStr, 10)
  244. phyMemSizeFloat = phyMemSizeFloat / 1048576
  245. phyMemSizeFloat = math.Floor(phyMemSizeFloat)
  246. totalRam = strconv.FormatFloat(phyMemSizeFloat, 'f', -1, 64) + "MB"
  247. // Used memory
  248. usedRAMSizeFloat := phyMemSizeFloat - freeMemSize
  249. usedRAMSizeFloat = math.Floor(usedRAMSizeFloat)
  250. usedRam = strconv.FormatFloat(usedRAMSizeFloat, 'f', -1, 64) + "MB"
  251. usedPercentage = usedRAMSizeFloat / phyMemSizeFloat * 100
  252. return usedRam, totalRam, usedPercentage
  253. }
  254. return usedRam, totalRam, usedPercentage
  255. }