usageinfo.go 10 KB

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