github.com/pfcoder/quorum@v2.0.3-0.20180501191142-d4a1b0958135+incompatible/metrics/metrics.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package metrics provides general system and process level metrics collection. 18 package metrics 19 20 import ( 21 "os" 22 "runtime" 23 "strings" 24 "time" 25 26 "github.com/ethereum/go-ethereum/log" 27 "github.com/rcrowley/go-metrics" 28 "github.com/rcrowley/go-metrics/exp" 29 ) 30 31 // MetricsEnabledFlag is the CLI flag name to use to enable metrics collections. 32 const MetricsEnabledFlag = "metrics" 33 34 // Enabled is the flag specifying if metrics are enable or not. 35 var Enabled = false 36 37 // Init enables or disables the metrics system. Since we need this to run before 38 // any other code gets to create meters and timers, we'll actually do an ugly hack 39 // and peek into the command line args for the metrics flag. 40 func init() { 41 for _, arg := range os.Args { 42 if strings.TrimLeft(arg, "-") == MetricsEnabledFlag { 43 log.Info("Enabling metrics collection") 44 Enabled = true 45 } 46 } 47 exp.Exp(metrics.DefaultRegistry) 48 } 49 50 // NewCounter create a new metrics Counter, either a real one of a NOP stub depending 51 // on the metrics flag. 52 func NewCounter(name string) metrics.Counter { 53 if !Enabled { 54 return new(metrics.NilCounter) 55 } 56 return metrics.GetOrRegisterCounter(name, metrics.DefaultRegistry) 57 } 58 59 // NewMeter create a new metrics Meter, either a real one of a NOP stub depending 60 // on the metrics flag. 61 func NewMeter(name string) metrics.Meter { 62 if !Enabled { 63 return new(metrics.NilMeter) 64 } 65 return metrics.GetOrRegisterMeter(name, metrics.DefaultRegistry) 66 } 67 68 // NewTimer create a new metrics Timer, either a real one of a NOP stub depending 69 // on the metrics flag. 70 func NewTimer(name string) metrics.Timer { 71 if !Enabled { 72 return new(metrics.NilTimer) 73 } 74 return metrics.GetOrRegisterTimer(name, metrics.DefaultRegistry) 75 } 76 77 // CollectProcessMetrics periodically collects various metrics about the running 78 // process. 79 func CollectProcessMetrics(refresh time.Duration) { 80 // Short circuit if the metrics system is disabled 81 if !Enabled { 82 return 83 } 84 // Create the various data collectors 85 memstats := make([]*runtime.MemStats, 2) 86 diskstats := make([]*DiskStats, 2) 87 for i := 0; i < len(memstats); i++ { 88 memstats[i] = new(runtime.MemStats) 89 diskstats[i] = new(DiskStats) 90 } 91 // Define the various metrics to collect 92 memAllocs := metrics.GetOrRegisterMeter("system/memory/allocs", metrics.DefaultRegistry) 93 memFrees := metrics.GetOrRegisterMeter("system/memory/frees", metrics.DefaultRegistry) 94 memInuse := metrics.GetOrRegisterMeter("system/memory/inuse", metrics.DefaultRegistry) 95 memPauses := metrics.GetOrRegisterMeter("system/memory/pauses", metrics.DefaultRegistry) 96 97 var diskReads, diskReadBytes, diskWrites, diskWriteBytes metrics.Meter 98 if err := ReadDiskStats(diskstats[0]); err == nil { 99 diskReads = metrics.GetOrRegisterMeter("system/disk/readcount", metrics.DefaultRegistry) 100 diskReadBytes = metrics.GetOrRegisterMeter("system/disk/readdata", metrics.DefaultRegistry) 101 diskWrites = metrics.GetOrRegisterMeter("system/disk/writecount", metrics.DefaultRegistry) 102 diskWriteBytes = metrics.GetOrRegisterMeter("system/disk/writedata", metrics.DefaultRegistry) 103 } else { 104 log.Debug("Failed to read disk metrics", "err", err) 105 } 106 // Iterate loading the different stats and updating the meters 107 for i := 1; ; i++ { 108 runtime.ReadMemStats(memstats[i%2]) 109 memAllocs.Mark(int64(memstats[i%2].Mallocs - memstats[(i-1)%2].Mallocs)) 110 memFrees.Mark(int64(memstats[i%2].Frees - memstats[(i-1)%2].Frees)) 111 memInuse.Mark(int64(memstats[i%2].Alloc - memstats[(i-1)%2].Alloc)) 112 memPauses.Mark(int64(memstats[i%2].PauseTotalNs - memstats[(i-1)%2].PauseTotalNs)) 113 114 if ReadDiskStats(diskstats[i%2]) == nil { 115 diskReads.Mark(int64(diskstats[i%2].ReadCount - diskstats[(i-1)%2].ReadCount)) 116 diskReadBytes.Mark(int64(diskstats[i%2].ReadBytes - diskstats[(i-1)%2].ReadBytes)) 117 diskWrites.Mark(int64(diskstats[i%2].WriteCount - diskstats[(i-1)%2].WriteCount)) 118 diskWriteBytes.Mark(int64(diskstats[i%2].WriteBytes - diskstats[(i-1)%2].WriteBytes)) 119 } 120 time.Sleep(refresh) 121 } 122 }