github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/metrics/metrics.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 // Go port of Coda Hale's Metrics library 19 // 20 // <https://github.com/rcrowley/go-metrics> 21 // 22 // Coda Hale's original work: <https://github.com/codahale/metrics> 23 package metrics 24 25 import ( 26 "os" 27 "runtime" 28 "strings" 29 "time" 30 31 "github.com/AigarNetwork/aigar/log" 32 ) 33 34 // Enabled is checked by the constructor functions for all of the 35 // standard metrics. If it is true, the metric returned is a stub. 36 // 37 // This global kill-switch helps quantify the observer effect and makes 38 // for less cluttered pprof profiles. 39 var Enabled = false 40 41 // EnabledExpensive is a soft-flag meant for external packages to check if costly 42 // metrics gathering is allowed or not. The goal is to separate standard metrics 43 // for health monitoring and debug metrics that might impact runtime performance. 44 var EnabledExpensive = false 45 46 // enablerFlags is the CLI flag names to use to enable metrics collections. 47 var enablerFlags = []string{"metrics"} 48 49 // expensiveEnablerFlags is the CLI flag names to use to enable metrics collections. 50 var expensiveEnablerFlags = []string{"metrics.expensive"} 51 52 // Init enables or disables the metrics system. Since we need this to run before 53 // any other code gets to create meters and timers, we'll actually do an ugly hack 54 // and peek into the command line args for the metrics flag. 55 func init() { 56 for _, arg := range os.Args { 57 flag := strings.TrimLeft(arg, "-") 58 59 for _, enabler := range enablerFlags { 60 if !Enabled && flag == enabler { 61 log.Info("Enabling metrics collection") 62 Enabled = true 63 } 64 } 65 for _, enabler := range expensiveEnablerFlags { 66 if !EnabledExpensive && flag == enabler { 67 log.Info("Enabling expensive metrics collection") 68 EnabledExpensive = true 69 } 70 } 71 } 72 } 73 74 // CollectProcessMetrics periodically collects various metrics about the running 75 // process. 76 func CollectProcessMetrics(refresh time.Duration) { 77 // Short circuit if the metrics system is disabled 78 if !Enabled { 79 return 80 } 81 refreshFreq := int64(refresh / time.Second) 82 83 // Create the various data collectors 84 cpuStats := make([]*CPUStats, 2) 85 memstats := make([]*runtime.MemStats, 2) 86 diskstats := make([]*DiskStats, 2) 87 for i := 0; i < len(memstats); i++ { 88 cpuStats[i] = new(CPUStats) 89 memstats[i] = new(runtime.MemStats) 90 diskstats[i] = new(DiskStats) 91 } 92 // Define the various metrics to collect 93 var ( 94 cpuSysLoad = GetOrRegisterGauge("system/cpu/sysload", DefaultRegistry) 95 cpuSysWait = GetOrRegisterGauge("system/cpu/syswait", DefaultRegistry) 96 cpuProcLoad = GetOrRegisterGauge("system/cpu/procload", DefaultRegistry) 97 cpuThreads = GetOrRegisterGauge("system/cpu/threads", DefaultRegistry) 98 cpuGoroutines = GetOrRegisterGauge("system/cpu/goroutines", DefaultRegistry) 99 100 memPauses = GetOrRegisterMeter("system/memory/pauses", DefaultRegistry) 101 memAllocs = GetOrRegisterMeter("system/memory/allocs", DefaultRegistry) 102 memFrees = GetOrRegisterMeter("system/memory/frees", DefaultRegistry) 103 memHeld = GetOrRegisterGauge("system/memory/held", DefaultRegistry) 104 memUsed = GetOrRegisterGauge("system/memory/used", DefaultRegistry) 105 106 diskReads = GetOrRegisterMeter("system/disk/readcount", DefaultRegistry) 107 diskReadBytes = GetOrRegisterMeter("system/disk/readdata", DefaultRegistry) 108 diskReadBytesCounter = GetOrRegisterCounter("system/disk/readbytes", DefaultRegistry) 109 diskWrites = GetOrRegisterMeter("system/disk/writecount", DefaultRegistry) 110 diskWriteBytes = GetOrRegisterMeter("system/disk/writedata", DefaultRegistry) 111 diskWriteBytesCounter = GetOrRegisterCounter("system/disk/writebytes", DefaultRegistry) 112 ) 113 // Iterate loading the different stats and updating the meters 114 for i := 1; ; i++ { 115 location1 := i % 2 116 location2 := (i - 1) % 2 117 118 ReadCPUStats(cpuStats[location1]) 119 cpuSysLoad.Update((cpuStats[location1].GlobalTime - cpuStats[location2].GlobalTime) / refreshFreq) 120 cpuSysWait.Update((cpuStats[location1].GlobalWait - cpuStats[location2].GlobalWait) / refreshFreq) 121 cpuProcLoad.Update((cpuStats[location1].LocalTime - cpuStats[location2].LocalTime) / refreshFreq) 122 cpuThreads.Update(int64(threadCreateProfile.Count())) 123 cpuGoroutines.Update(int64(runtime.NumGoroutine())) 124 125 runtime.ReadMemStats(memstats[location1]) 126 memPauses.Mark(int64(memstats[location1].PauseTotalNs - memstats[location2].PauseTotalNs)) 127 memAllocs.Mark(int64(memstats[location1].Mallocs - memstats[location2].Mallocs)) 128 memFrees.Mark(int64(memstats[location1].Frees - memstats[location2].Frees)) 129 memHeld.Update(int64(memstats[location1].HeapSys - memstats[location1].HeapReleased)) 130 memUsed.Update(int64(memstats[location1].Alloc)) 131 132 if ReadDiskStats(diskstats[location1]) == nil { 133 diskReads.Mark(diskstats[location1].ReadCount - diskstats[location2].ReadCount) 134 diskReadBytes.Mark(diskstats[location1].ReadBytes - diskstats[location2].ReadBytes) 135 diskWrites.Mark(diskstats[location1].WriteCount - diskstats[location2].WriteCount) 136 diskWriteBytes.Mark(diskstats[location1].WriteBytes - diskstats[location2].WriteBytes) 137 138 diskReadBytesCounter.Inc(diskstats[location1].ReadBytes - diskstats[location2].ReadBytes) 139 diskWriteBytesCounter.Inc(diskstats[location1].WriteBytes - diskstats[location2].WriteBytes) 140 } 141 time.Sleep(refresh) 142 } 143 }