2019-07-22 12:17:27 +03:00
|
|
|
// Copyright 2019 The go-ethereum Authors
|
2019-03-13 14:53:52 +02:00
|
|
|
// 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},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|