147 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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},
 | |
| 				},
 | |
| 			})
 | |
| 		}
 | |
| 	}
 | |
| }
 |