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