usageinfo.go 9.1 KB

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