system.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright 2019 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package dashboard
  17. import (
  18. "runtime"
  19. "time"
  20. "github.com/elastic/gosigar"
  21. "github.com/ethereum/go-ethereum/metrics"
  22. "github.com/ethereum/go-ethereum/p2p"
  23. )
  24. // meterCollector returns a function, which retrieves the count of a specific meter.
  25. func meterCollector(name string) func() int64 {
  26. if meter := metrics.Get(name); meter != nil {
  27. m := meter.(metrics.Meter)
  28. return func() int64 {
  29. return m.Count()
  30. }
  31. }
  32. return func() int64 {
  33. return 0
  34. }
  35. }
  36. // collectSystemData gathers data about the system and sends it to the clients.
  37. func (db *Dashboard) collectSystemData() {
  38. defer db.wg.Done()
  39. systemCPUUsage := gosigar.Cpu{}
  40. systemCPUUsage.Get()
  41. var (
  42. mem runtime.MemStats
  43. collectNetworkIngress = meterCollector(p2p.MetricsInboundTraffic)
  44. collectNetworkEgress = meterCollector(p2p.MetricsOutboundTraffic)
  45. collectDiskRead = meterCollector("eth/db/chaindata/disk/read")
  46. collectDiskWrite = meterCollector("eth/db/chaindata/disk/write")
  47. prevNetworkIngress = collectNetworkIngress()
  48. prevNetworkEgress = collectNetworkEgress()
  49. prevProcessCPUTime = getProcessCPUTime()
  50. prevSystemCPUUsage = systemCPUUsage
  51. prevDiskRead = collectDiskRead()
  52. prevDiskWrite = collectDiskWrite()
  53. frequency = float64(db.config.Refresh / time.Second)
  54. numCPU = float64(runtime.NumCPU())
  55. )
  56. for {
  57. select {
  58. case errc := <-db.quit:
  59. errc <- nil
  60. return
  61. case <-time.After(db.config.Refresh):
  62. systemCPUUsage.Get()
  63. var (
  64. curNetworkIngress = collectNetworkIngress()
  65. curNetworkEgress = collectNetworkEgress()
  66. curProcessCPUTime = getProcessCPUTime()
  67. curSystemCPUUsage = systemCPUUsage
  68. curDiskRead = collectDiskRead()
  69. curDiskWrite = collectDiskWrite()
  70. deltaNetworkIngress = float64(curNetworkIngress - prevNetworkIngress)
  71. deltaNetworkEgress = float64(curNetworkEgress - prevNetworkEgress)
  72. deltaProcessCPUTime = curProcessCPUTime - prevProcessCPUTime
  73. deltaSystemCPUUsage = curSystemCPUUsage.Delta(prevSystemCPUUsage)
  74. deltaDiskRead = curDiskRead - prevDiskRead
  75. deltaDiskWrite = curDiskWrite - prevDiskWrite
  76. )
  77. prevNetworkIngress = curNetworkIngress
  78. prevNetworkEgress = curNetworkEgress
  79. prevProcessCPUTime = curProcessCPUTime
  80. prevSystemCPUUsage = curSystemCPUUsage
  81. prevDiskRead = curDiskRead
  82. prevDiskWrite = curDiskWrite
  83. runtime.ReadMemStats(&mem)
  84. activeMemory := &ChartEntry{
  85. Value: float64(mem.Alloc) / frequency,
  86. }
  87. virtualMemory := &ChartEntry{
  88. Value: float64(mem.Sys) / frequency,
  89. }
  90. networkIngress := &ChartEntry{
  91. Value: deltaNetworkIngress / frequency,
  92. }
  93. networkEgress := &ChartEntry{
  94. Value: deltaNetworkEgress / frequency,
  95. }
  96. processCPU := &ChartEntry{
  97. Value: deltaProcessCPUTime / frequency / numCPU * 100,
  98. }
  99. systemCPU := &ChartEntry{
  100. Value: float64(deltaSystemCPUUsage.Sys+deltaSystemCPUUsage.User) / frequency / numCPU,
  101. }
  102. diskRead := &ChartEntry{
  103. Value: float64(deltaDiskRead) / frequency,
  104. }
  105. diskWrite := &ChartEntry{
  106. Value: float64(deltaDiskWrite) / frequency,
  107. }
  108. db.sysLock.Lock()
  109. sys := db.history.System
  110. sys.ActiveMemory = append(sys.ActiveMemory[1:], activeMemory)
  111. sys.VirtualMemory = append(sys.VirtualMemory[1:], virtualMemory)
  112. sys.NetworkIngress = append(sys.NetworkIngress[1:], networkIngress)
  113. sys.NetworkEgress = append(sys.NetworkEgress[1:], networkEgress)
  114. sys.ProcessCPU = append(sys.ProcessCPU[1:], processCPU)
  115. sys.SystemCPU = append(sys.SystemCPU[1:], systemCPU)
  116. sys.DiskRead = append(sys.DiskRead[1:], diskRead)
  117. sys.DiskWrite = append(sys.DiskWrite[1:], diskWrite)
  118. db.sysLock.Unlock()
  119. db.sendToAll(&Message{
  120. System: &SystemMessage{
  121. ActiveMemory: ChartEntries{activeMemory},
  122. VirtualMemory: ChartEntries{virtualMemory},
  123. NetworkIngress: ChartEntries{networkIngress},
  124. NetworkEgress: ChartEntries{networkEgress},
  125. ProcessCPU: ChartEntries{processCPU},
  126. SystemCPU: ChartEntries{systemCPU},
  127. DiskRead: ChartEntries{diskRead},
  128. DiskWrite: ChartEntries{diskWrite},
  129. },
  130. })
  131. }
  132. }
  133. }