| 
									
										
										
										
											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}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |