github.com/dominant-strategies/go-quai@v0.28.2/internal/debug/flags.go (about) 1 // Copyright 2016 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 debug 18 19 import ( 20 "fmt" 21 "net/http" 22 _ "net/http/pprof" 23 "runtime" 24 25 "github.com/dominant-strategies/go-quai/log" 26 "github.com/dominant-strategies/go-quai/metrics" 27 "github.com/dominant-strategies/go-quai/metrics/exp" 28 "github.com/fjl/memsize/memsizeui" 29 "gopkg.in/urfave/cli.v1" 30 ) 31 32 var Memsize memsizeui.Handler 33 34 var ( 35 verbosityFlag = cli.IntFlag{ 36 Name: "verbosity", 37 Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail", 38 Value: 3, 39 } 40 vmoduleFlag = cli.StringFlag{ 41 Name: "vmodule", 42 Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)", 43 Value: "", 44 } 45 logjsonFlag = cli.BoolFlag{ 46 Name: "log.json", 47 Usage: "Format logs with JSON", 48 } 49 backtraceAtFlag = cli.StringFlag{ 50 Name: "log.backtrace", 51 Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")", 52 Value: "", 53 } 54 debugFlag = cli.BoolFlag{ 55 Name: "log.debug", 56 Usage: "Prepends log messages with call-site location (file and line number)", 57 } 58 pprofFlag = cli.BoolFlag{ 59 Name: "pprof", 60 Usage: "Enable the pprof HTTP server", 61 } 62 pprofPortFlag = cli.IntFlag{ 63 Name: "pprof.port", 64 Usage: "pprof HTTP server listening port", 65 Value: 6060, 66 } 67 pprofAddrFlag = cli.StringFlag{ 68 Name: "pprof.addr", 69 Usage: "pprof HTTP server listening interface", 70 Value: "127.0.0.1", 71 } 72 memprofilerateFlag = cli.IntFlag{ 73 Name: "pprof.memprofilerate", 74 Usage: "Turn on memory profiling with the given rate", 75 Value: runtime.MemProfileRate, 76 } 77 blockprofilerateFlag = cli.IntFlag{ 78 Name: "pprof.blockprofilerate", 79 Usage: "Turn on block profiling with the given rate", 80 } 81 cpuprofileFlag = cli.StringFlag{ 82 Name: "pprof.cpuprofile", 83 Usage: "Write CPU profile to the given file", 84 } 85 traceFlag = cli.StringFlag{ 86 Name: "trace", 87 Usage: "Write execution trace to the given file", 88 } 89 // (Deprecated April 2020) 90 legacyPprofPortFlag = cli.IntFlag{ 91 Name: "pprofport", 92 Usage: "pprof HTTP server listening port (deprecated, use --pprof.port)", 93 Value: 6060, 94 } 95 legacyPprofAddrFlag = cli.StringFlag{ 96 Name: "pprofaddr", 97 Usage: "pprof HTTP server listening interface (deprecated, use --pprof.addr)", 98 Value: "127.0.0.1", 99 } 100 legacyMemprofilerateFlag = cli.IntFlag{ 101 Name: "memprofilerate", 102 Usage: "Turn on memory profiling with the given rate (deprecated, use --pprof.memprofilerate)", 103 Value: runtime.MemProfileRate, 104 } 105 legacyBlockprofilerateFlag = cli.IntFlag{ 106 Name: "blockprofilerate", 107 Usage: "Turn on block profiling with the given rate (deprecated, use --pprof.blockprofilerate)", 108 } 109 legacyCpuprofileFlag = cli.StringFlag{ 110 Name: "cpuprofile", 111 Usage: "Write CPU profile to the given file (deprecated, use --pprof.cpuprofile)", 112 } 113 legacyBacktraceAtFlag = cli.StringFlag{ 114 Name: "backtrace", 115 Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\") (deprecated, use --log.backtrace)", 116 Value: "", 117 } 118 legacyDebugFlag = cli.BoolFlag{ 119 Name: "debug", 120 Usage: "Prepends log messages with call-site location (file and line number) (deprecated, use --log.debug)", 121 } 122 ) 123 124 // Flags holds all command-line flags required for debugging. 125 var Flags = []cli.Flag{ 126 verbosityFlag, 127 vmoduleFlag, 128 logjsonFlag, 129 backtraceAtFlag, 130 debugFlag, 131 pprofFlag, 132 pprofAddrFlag, 133 pprofPortFlag, 134 memprofilerateFlag, 135 blockprofilerateFlag, 136 cpuprofileFlag, 137 traceFlag, 138 } 139 140 // This is the list of deprecated debugging flags. 141 var DeprecatedFlags = []cli.Flag{ 142 legacyPprofPortFlag, 143 legacyPprofAddrFlag, 144 legacyMemprofilerateFlag, 145 legacyBlockprofilerateFlag, 146 legacyCpuprofileFlag, 147 legacyBacktraceAtFlag, 148 legacyDebugFlag, 149 } 150 151 func init() { 152 } 153 154 // Setup initializes profiling and logging based on the CLI flags. 155 // It should be called as early as possible in the program. 156 func Setup(ctx *cli.Context) error { 157 158 // profiling, tracing 159 runtime.MemProfileRate = memprofilerateFlag.Value 160 if ctx.GlobalIsSet(legacyMemprofilerateFlag.Name) { 161 runtime.MemProfileRate = ctx.GlobalInt(legacyMemprofilerateFlag.Name) 162 log.Warn("The flag --memprofilerate is deprecated and will be removed in the future, please use --pprof.memprofilerate") 163 } 164 if ctx.GlobalIsSet(memprofilerateFlag.Name) { 165 runtime.MemProfileRate = ctx.GlobalInt(memprofilerateFlag.Name) 166 } 167 168 blockProfileRate := blockprofilerateFlag.Value 169 if ctx.GlobalIsSet(legacyBlockprofilerateFlag.Name) { 170 blockProfileRate = ctx.GlobalInt(legacyBlockprofilerateFlag.Name) 171 log.Warn("The flag --blockprofilerate is deprecated and will be removed in the future, please use --pprof.blockprofilerate") 172 } 173 if ctx.GlobalIsSet(blockprofilerateFlag.Name) { 174 blockProfileRate = ctx.GlobalInt(blockprofilerateFlag.Name) 175 } 176 Handler.SetBlockProfileRate(blockProfileRate) 177 178 if traceFile := ctx.GlobalString(traceFlag.Name); traceFile != "" { 179 if err := Handler.StartGoTrace(traceFile); err != nil { 180 return err 181 } 182 } 183 184 if cpuFile := ctx.GlobalString(cpuprofileFlag.Name); cpuFile != "" { 185 if err := Handler.StartCPUProfile(cpuFile); err != nil { 186 return err 187 } 188 } 189 190 // pprof server 191 if ctx.GlobalBool(pprofFlag.Name) { 192 listenHost := ctx.GlobalString(pprofAddrFlag.Name) 193 194 port := ctx.GlobalInt(pprofPortFlag.Name) 195 196 address := fmt.Sprintf("%s:%d", listenHost, port) 197 // This context value ("metrics.addr") represents the utils.MetricsHTTPFlag.Name. 198 // It cannot be imported because it will cause a cyclical dependency. 199 StartPProf(address, !ctx.GlobalIsSet("metrics.addr")) 200 } 201 return nil 202 } 203 204 func StartPProf(address string, withMetrics bool) { 205 // Hook go-metrics into expvar on any /debug/metrics request, load all vars 206 // from the registry into expvar, and execute regular expvar handler. 207 if withMetrics { 208 exp.Exp(metrics.DefaultRegistry) 209 } 210 http.Handle("/memsize/", http.StripPrefix("/memsize", &Memsize)) 211 log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address)) 212 go func() { 213 if err := http.ListenAndServe(address, nil); err != nil { 214 log.Error("Failure in running pprof server", "err", err) 215 } 216 }() 217 } 218 219 // Exit stops all running profiles, flushing their output to the 220 // respective file. 221 func Exit() { 222 Handler.StopCPUProfile() 223 Handler.StopGoTrace() 224 }