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