record.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package analytic
  2. import (
  3. stdnet "net"
  4. "runtime"
  5. "time"
  6. "github.com/shirou/gopsutil/v4/cpu"
  7. "github.com/shirou/gopsutil/v4/disk"
  8. "github.com/shirou/gopsutil/v4/net"
  9. "github.com/uozi-tech/cosy/logger"
  10. )
  11. func getTotalDiskIO() (read, write uint64) {
  12. diskIOCounters, err := disk.IOCounters()
  13. if err != nil {
  14. logger.Error(err)
  15. return
  16. }
  17. for _, v := range diskIOCounters {
  18. write += v.WriteCount
  19. read += v.ReadCount
  20. }
  21. return
  22. }
  23. func recordCpu(now time.Time) {
  24. cpuTimesBefore, err := cpu.Times(false)
  25. if err != nil {
  26. logger.Error(err)
  27. return
  28. }
  29. time.Sleep(1000 * time.Millisecond)
  30. cpuTimesAfter, err := cpu.Times(false)
  31. if err != nil {
  32. logger.Error(err)
  33. return
  34. }
  35. threadNum := runtime.GOMAXPROCS(0)
  36. cpuUserUsage := (cpuTimesAfter[0].User - cpuTimesBefore[0].User) / (float64(1000*threadNum) / 1000)
  37. cpuUserUsage *= 100
  38. cpuSystemUsage := (cpuTimesAfter[0].System - cpuTimesBefore[0].System) / (float64(1000*threadNum) / 1000)
  39. cpuSystemUsage *= 100
  40. u := Usage[float64]{
  41. Time: now,
  42. Usage: cpuUserUsage,
  43. }
  44. CpuUserRecord = append(CpuUserRecord, u)
  45. s := Usage[float64]{
  46. Time: now,
  47. Usage: cpuUserUsage + cpuSystemUsage,
  48. }
  49. CpuTotalRecord = append(CpuTotalRecord, s)
  50. if len(CpuUserRecord) > 100 {
  51. CpuUserRecord = CpuUserRecord[1:]
  52. }
  53. if len(CpuTotalRecord) > 100 {
  54. CpuTotalRecord = CpuTotalRecord[1:]
  55. }
  56. }
  57. func recordNetwork(now time.Time) {
  58. // Get separate statistics for each interface
  59. networkStats, err := net.IOCounters(true)
  60. if err != nil {
  61. logger.Error(err)
  62. return
  63. }
  64. if len(networkStats) == 0 {
  65. return
  66. }
  67. // Get all network interfaces
  68. interfaces, err := stdnet.Interfaces()
  69. if err != nil {
  70. logger.Error(err)
  71. return
  72. }
  73. var totalBytesRecv uint64
  74. var totalBytesSent uint64
  75. var externalInterfaceFound bool
  76. // Iterate through all interfaces to find external ones
  77. for _, iface := range interfaces {
  78. // Skip interfaces that are down
  79. if iface.Flags&stdnet.FlagUp == 0 {
  80. continue
  81. }
  82. // Get IP addresses for the interface
  83. addrs, err := iface.Addrs()
  84. if err != nil {
  85. logger.Error(err)
  86. continue
  87. }
  88. // Check if this is an external interface
  89. for _, addr := range addrs {
  90. if ipNet, ok := addr.(*stdnet.IPNet); ok {
  91. // Exclude loopback addresses and private IPs
  92. if !ipNet.IP.IsLoopback() {
  93. // Found external interface, accumulate its statistics
  94. for _, stat := range networkStats {
  95. if stat.Name == iface.Name {
  96. totalBytesRecv += stat.BytesRecv
  97. totalBytesSent += stat.BytesSent
  98. externalInterfaceFound = true
  99. break
  100. }
  101. }
  102. break
  103. }
  104. }
  105. }
  106. }
  107. // If no external interface is found, use fallback option
  108. if !externalInterfaceFound {
  109. // Fallback: use all non-loopback interfaces
  110. for _, iface := range interfaces {
  111. if iface.Flags&stdnet.FlagLoopback == 0 && iface.Flags&stdnet.FlagUp != 0 {
  112. for _, stat := range networkStats {
  113. if stat.Name == iface.Name {
  114. totalBytesRecv += stat.BytesRecv
  115. totalBytesSent += stat.BytesSent
  116. break
  117. }
  118. }
  119. }
  120. }
  121. }
  122. LastNetRecv = totalBytesRecv
  123. LastNetSent = totalBytesSent
  124. NetRecvRecord = append(NetRecvRecord, Usage[uint64]{
  125. Time: now,
  126. Usage: totalBytesRecv - LastNetRecv,
  127. })
  128. NetSentRecord = append(NetSentRecord, Usage[uint64]{
  129. Time: now,
  130. Usage: totalBytesSent - LastNetSent,
  131. })
  132. if len(NetRecvRecord) > 100 {
  133. NetRecvRecord = NetRecvRecord[1:]
  134. }
  135. if len(NetSentRecord) > 100 {
  136. NetSentRecord = NetSentRecord[1:]
  137. }
  138. }
  139. func recordDiskIO(now time.Time) {
  140. readCount, writeCount := getTotalDiskIO()
  141. DiskReadRecord = append(DiskReadRecord, Usage[uint64]{
  142. Time: now,
  143. Usage: readCount - LastDiskReads,
  144. })
  145. DiskWriteRecord = append(DiskWriteRecord, Usage[uint64]{
  146. Time: now,
  147. Usage: writeCount - LastDiskWrites,
  148. })
  149. if len(DiskReadRecord) > 100 {
  150. DiskReadRecord = DiskReadRecord[1:]
  151. }
  152. if len(DiskWriteRecord) > 100 {
  153. DiskWriteRecord = DiskWriteRecord[1:]
  154. }
  155. LastDiskWrites = writeCount
  156. LastDiskReads = readCount
  157. }