github.com/core-coin/go-core/v2@v2.1.9/metrics/metrics.go (about) 1 // Go port of Coda Hale's Metrics library 2 // 3 // <https://github.com/rcrowley/go-metrics> 4 // 5 // Coda Hale's original work: <https://github.com/codahale/metrics> 6 package metrics 7 8 import ( 9 "os" 10 "runtime" 11 "strings" 12 "time" 13 14 "github.com/core-coin/go-core/v2/log" 15 ) 16 17 // Enabled is checked by the constructor functions for all of the 18 // standard metrics. If it is true, the metric returned is a stub. 19 // 20 // This global kill-switch helps quantify the observer effect and makes 21 // for less cluttered pprof profiles. 22 var Enabled = false 23 24 // EnabledExpensive is a soft-flag meant for external packages to check if costly 25 // metrics gathering is allowed or not. The goal is to separate standard metrics 26 // for health monitoring and debug metrics that might impact runtime performance. 27 var EnabledExpensive = false 28 29 // enablerFlags is the CLI flag names to use to enable metrics collections. 30 var enablerFlags = []string{"metrics"} 31 32 // expensiveEnablerFlags is the CLI flag names to use to enable metrics collections. 33 var expensiveEnablerFlags = []string{"metrics.expensive"} 34 35 // Init enables or disables the metrics system. Since we need this to run before 36 // any other code gets to create meters and timers, we'll actually do an ugly hack 37 // and peek into the command line args for the metrics flag. 38 func init() { 39 for _, arg := range os.Args { 40 flag := strings.TrimLeft(arg, "-") 41 42 for _, enabler := range enablerFlags { 43 if !Enabled && flag == enabler { 44 log.Info("Enabling metrics collection") 45 Enabled = true 46 } 47 } 48 for _, enabler := range expensiveEnablerFlags { 49 if !EnabledExpensive && flag == enabler { 50 log.Info("Enabling expensive metrics collection") 51 EnabledExpensive = true 52 } 53 } 54 } 55 } 56 57 // CollectProcessMetrics periodically collects various metrics about the running 58 // process. 59 func CollectProcessMetrics(refresh time.Duration) { 60 // Short circuit if the metrics system is disabled 61 if !Enabled { 62 return 63 } 64 refreshFreq := int64(refresh / time.Second) 65 66 // Create the various data collectors 67 cpuStats := make([]*CPUStats, 2) 68 memstats := make([]*runtime.MemStats, 2) 69 diskstats := make([]*DiskStats, 2) 70 for i := 0; i < len(memstats); i++ { 71 cpuStats[i] = new(CPUStats) 72 memstats[i] = new(runtime.MemStats) 73 diskstats[i] = new(DiskStats) 74 } 75 // Define the various metrics to collect 76 var ( 77 cpuSysLoad = GetOrRegisterGauge("system/cpu/sysload", DefaultRegistry) 78 cpuSysWait = GetOrRegisterGauge("system/cpu/syswait", DefaultRegistry) 79 cpuProcLoad = GetOrRegisterGauge("system/cpu/procload", DefaultRegistry) 80 cpuThreads = GetOrRegisterGauge("system/cpu/threads", DefaultRegistry) 81 cpuGoroutines = GetOrRegisterGauge("system/cpu/goroutines", DefaultRegistry) 82 83 memPauses = GetOrRegisterMeter("system/memory/pauses", DefaultRegistry) 84 memAllocs = GetOrRegisterMeter("system/memory/allocs", DefaultRegistry) 85 memFrees = GetOrRegisterMeter("system/memory/frees", DefaultRegistry) 86 memHeld = GetOrRegisterGauge("system/memory/held", DefaultRegistry) 87 memUsed = GetOrRegisterGauge("system/memory/used", DefaultRegistry) 88 89 diskReads = GetOrRegisterMeter("system/disk/readcount", DefaultRegistry) 90 diskReadBytes = GetOrRegisterMeter("system/disk/readdata", DefaultRegistry) 91 diskReadBytesCounter = GetOrRegisterCounter("system/disk/readbytes", DefaultRegistry) 92 diskWrites = GetOrRegisterMeter("system/disk/writecount", DefaultRegistry) 93 diskWriteBytes = GetOrRegisterMeter("system/disk/writedata", DefaultRegistry) 94 diskWriteBytesCounter = GetOrRegisterCounter("system/disk/writebytes", DefaultRegistry) 95 discFreeSpace = GetOrRegisterMeter("system/disk/freespace", DefaultRegistry) 96 ) 97 // Iterate loading the different stats and updating the meters 98 for i := 1; ; i++ { 99 location1 := i % 2 100 location2 := (i - 1) % 2 101 102 ReadCPUStats(cpuStats[location1]) 103 cpuSysLoad.Update((cpuStats[location1].GlobalTime - cpuStats[location2].GlobalTime) / refreshFreq) 104 cpuSysWait.Update((cpuStats[location1].GlobalWait - cpuStats[location2].GlobalWait) / refreshFreq) 105 cpuProcLoad.Update((cpuStats[location1].LocalTime - cpuStats[location2].LocalTime) / refreshFreq) 106 cpuThreads.Update(int64(threadCreateProfile.Count())) 107 cpuGoroutines.Update(int64(runtime.NumGoroutine())) 108 109 runtime.ReadMemStats(memstats[location1]) 110 memPauses.Mark(int64(memstats[location1].PauseTotalNs - memstats[location2].PauseTotalNs)) 111 memAllocs.Mark(int64(memstats[location1].Mallocs - memstats[location2].Mallocs)) 112 memFrees.Mark(int64(memstats[location1].Frees - memstats[location2].Frees)) 113 memHeld.Update(int64(memstats[location1].HeapSys - memstats[location1].HeapReleased)) 114 memUsed.Update(int64(memstats[location1].Alloc)) 115 116 if ReadDiskStats(diskstats[location1]) == nil { 117 diskReads.Mark(diskstats[location1].ReadCount - diskstats[location2].ReadCount) 118 diskReadBytes.Mark(diskstats[location1].ReadBytes - diskstats[location2].ReadBytes) 119 diskWrites.Mark(diskstats[location1].WriteCount - diskstats[location2].WriteCount) 120 diskWriteBytes.Mark(diskstats[location1].WriteBytes - diskstats[location2].WriteBytes) 121 122 diskReadBytesCounter.Inc(diskstats[location1].ReadBytes - diskstats[location2].ReadBytes) 123 diskWriteBytesCounter.Inc(diskstats[location1].WriteBytes - diskstats[location2].WriteBytes) 124 discFreeSpace.Mark(diskstats[location1].FreeSpaceGB - diskstats[location2].FreeSpaceGB) 125 } 126 time.Sleep(refresh) 127 } 128 }