diff options
Diffstat (limited to 'dashboard/system.go')
-rw-r--r-- | dashboard/system.go | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/dashboard/system.go b/dashboard/system.go new file mode 100644 index 000000000..a880c5a72 --- /dev/null +++ b/dashboard/system.go @@ -0,0 +1,146 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +package dashboard + +import ( + "runtime" + "time" + + "github.com/elastic/gosigar" + "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/p2p" +) + +// meterCollector returns a function, which retrieves the count of a specific meter. +func meterCollector(name string) func() int64 { + if meter := metrics.Get(name); meter != nil { + m := meter.(metrics.Meter) + return func() int64 { + return m.Count() + } + } + return func() int64 { + return 0 + } +} + +// collectSystemData gathers data about the system and sends it to the clients. +func (db *Dashboard) collectSystemData() { + defer db.wg.Done() + + systemCPUUsage := gosigar.Cpu{} + systemCPUUsage.Get() + var ( + mem runtime.MemStats + + collectNetworkIngress = meterCollector(p2p.MetricsInboundTraffic) + collectNetworkEgress = meterCollector(p2p.MetricsOutboundTraffic) + collectDiskRead = meterCollector("eth/db/chaindata/disk/read") + collectDiskWrite = meterCollector("eth/db/chaindata/disk/write") + + prevNetworkIngress = collectNetworkIngress() + prevNetworkEgress = collectNetworkEgress() + prevProcessCPUTime = getProcessCPUTime() + prevSystemCPUUsage = systemCPUUsage + prevDiskRead = collectDiskRead() + prevDiskWrite = collectDiskWrite() + + frequency = float64(db.config.Refresh / time.Second) + numCPU = float64(runtime.NumCPU()) + ) + + for { + select { + case errc := <-db.quit: + errc <- nil + return + case <-time.After(db.config.Refresh): + systemCPUUsage.Get() + var ( + curNetworkIngress = collectNetworkIngress() + curNetworkEgress = collectNetworkEgress() + curProcessCPUTime = getProcessCPUTime() + curSystemCPUUsage = systemCPUUsage + curDiskRead = collectDiskRead() + curDiskWrite = collectDiskWrite() + + deltaNetworkIngress = float64(curNetworkIngress - prevNetworkIngress) + deltaNetworkEgress = float64(curNetworkEgress - prevNetworkEgress) + deltaProcessCPUTime = curProcessCPUTime - prevProcessCPUTime + deltaSystemCPUUsage = curSystemCPUUsage.Delta(prevSystemCPUUsage) + deltaDiskRead = curDiskRead - prevDiskRead + deltaDiskWrite = curDiskWrite - prevDiskWrite + ) + prevNetworkIngress = curNetworkIngress + prevNetworkEgress = curNetworkEgress + prevProcessCPUTime = curProcessCPUTime + prevSystemCPUUsage = curSystemCPUUsage + prevDiskRead = curDiskRead + prevDiskWrite = curDiskWrite + + runtime.ReadMemStats(&mem) + activeMemory := &ChartEntry{ + Value: float64(mem.Alloc) / frequency, + } + virtualMemory := &ChartEntry{ + Value: float64(mem.Sys) / frequency, + } + networkIngress := &ChartEntry{ + Value: deltaNetworkIngress / frequency, + } + networkEgress := &ChartEntry{ + Value: deltaNetworkEgress / frequency, + } + processCPU := &ChartEntry{ + Value: deltaProcessCPUTime / frequency / numCPU * 100, + } + systemCPU := &ChartEntry{ + Value: float64(deltaSystemCPUUsage.Sys+deltaSystemCPUUsage.User) / frequency / numCPU, + } + diskRead := &ChartEntry{ + Value: float64(deltaDiskRead) / frequency, + } + diskWrite := &ChartEntry{ + Value: float64(deltaDiskWrite) / frequency, + } + db.sysLock.Lock() + sys := db.history.System + sys.ActiveMemory = append(sys.ActiveMemory[1:], activeMemory) + sys.VirtualMemory = append(sys.VirtualMemory[1:], virtualMemory) + sys.NetworkIngress = append(sys.NetworkIngress[1:], networkIngress) + sys.NetworkEgress = append(sys.NetworkEgress[1:], networkEgress) + sys.ProcessCPU = append(sys.ProcessCPU[1:], processCPU) + sys.SystemCPU = append(sys.SystemCPU[1:], systemCPU) + sys.DiskRead = append(sys.DiskRead[1:], diskRead) + sys.DiskWrite = append(sys.DiskWrite[1:], diskWrite) + db.sysLock.Unlock() + + db.sendToAll(&Message{ + System: &SystemMessage{ + ActiveMemory: ChartEntries{activeMemory}, + VirtualMemory: ChartEntries{virtualMemory}, + NetworkIngress: ChartEntries{networkIngress}, + NetworkEgress: ChartEntries{networkEgress}, + ProcessCPU: ChartEntries{processCPU}, + SystemCPU: ChartEntries{systemCPU}, + DiskRead: ChartEntries{diskRead}, + DiskWrite: ChartEntries{diskWrite}, + }, + }) + } + } +} |