github.com/MetalBlockchain/subnet-evm@v0.4.9/internal/debug/flags.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2016 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package debug 28 29 import ( 30 "fmt" 31 "io" 32 "net/http" 33 _ "net/http/pprof" // nolint: gosec 34 "os" 35 "runtime" 36 37 "github.com/ethereum/go-ethereum/log" 38 "github.com/fjl/memsize/memsizeui" 39 "github.com/mattn/go-colorable" 40 "github.com/mattn/go-isatty" 41 "gopkg.in/urfave/cli.v1" 42 ) 43 44 var Memsize memsizeui.Handler 45 46 var ( 47 verbosityFlag = cli.IntFlag{ 48 Name: "verbosity", 49 Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail", 50 Value: 3, 51 } 52 vmoduleFlag = cli.StringFlag{ 53 Name: "vmodule", 54 Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)", 55 Value: "", 56 } 57 logjsonFlag = cli.BoolFlag{ 58 Name: "log.json", 59 Usage: "Format logs with JSON", 60 } 61 backtraceAtFlag = cli.StringFlag{ 62 Name: "log.backtrace", 63 Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")", 64 Value: "", 65 } 66 debugFlag = cli.BoolFlag{ 67 Name: "log.debug", 68 Usage: "Prepends log messages with call-site location (file and line number)", 69 } 70 pprofFlag = cli.BoolFlag{ 71 Name: "pprof", 72 Usage: "Enable the pprof HTTP server", 73 } 74 pprofPortFlag = cli.IntFlag{ 75 Name: "pprof.port", 76 Usage: "pprof HTTP server listening port", 77 Value: 6060, 78 } 79 pprofAddrFlag = cli.StringFlag{ 80 Name: "pprof.addr", 81 Usage: "pprof HTTP server listening interface", 82 Value: "127.0.0.1", 83 } 84 memprofilerateFlag = cli.IntFlag{ 85 Name: "pprof.memprofilerate", 86 Usage: "Turn on memory profiling with the given rate", 87 Value: runtime.MemProfileRate, 88 } 89 blockprofilerateFlag = cli.IntFlag{ 90 Name: "pprof.blockprofilerate", 91 Usage: "Turn on block profiling with the given rate", 92 } 93 cpuprofileFlag = cli.StringFlag{ 94 Name: "pprof.cpuprofile", 95 Usage: "Write CPU profile to the given file", 96 } 97 traceFlag = cli.StringFlag{ 98 Name: "trace", 99 Usage: "Write execution trace to the given file", 100 } 101 ) 102 103 // Flags holds all command-line flags required for debugging. 104 var Flags = []cli.Flag{ 105 verbosityFlag, 106 vmoduleFlag, 107 logjsonFlag, 108 backtraceAtFlag, 109 debugFlag, 110 pprofFlag, 111 pprofAddrFlag, 112 pprofPortFlag, 113 memprofilerateFlag, 114 blockprofilerateFlag, 115 cpuprofileFlag, 116 traceFlag, 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 // Setup initializes profiling and logging based on the CLI flags. 128 // It should be called as early as possible in the program. 129 func Setup(ctx *cli.Context) error { 130 var ostream log.Handler 131 output := io.Writer(os.Stderr) 132 if ctx.GlobalBool(logjsonFlag.Name) { 133 ostream = log.StreamHandler(output, log.JSONFormat()) 134 } else { 135 usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb" 136 if usecolor { 137 output = colorable.NewColorableStderr() 138 } 139 ostream = log.StreamHandler(output, log.TerminalFormat(usecolor)) 140 } 141 glogger.SetHandler(ostream) 142 143 // logging 144 verbosity := ctx.GlobalInt(verbosityFlag.Name) 145 glogger.Verbosity(log.Lvl(verbosity)) 146 vmodule := ctx.GlobalString(vmoduleFlag.Name) 147 glogger.Vmodule(vmodule) 148 149 debug := ctx.GlobalBool(debugFlag.Name) 150 if ctx.GlobalIsSet(debugFlag.Name) { 151 debug = ctx.GlobalBool(debugFlag.Name) 152 } 153 log.PrintOrigins(debug) 154 155 backtrace := ctx.GlobalString(backtraceAtFlag.Name) 156 glogger.BacktraceAt(backtrace) 157 158 log.Root().SetHandler(glogger) 159 160 // profiling, tracing 161 runtime.MemProfileRate = memprofilerateFlag.Value 162 if ctx.GlobalIsSet(memprofilerateFlag.Name) { 163 runtime.MemProfileRate = ctx.GlobalInt(memprofilerateFlag.Name) 164 } 165 166 blockProfileRate := ctx.GlobalInt(blockprofilerateFlag.Name) 167 Handler.SetBlockProfileRate(blockProfileRate) 168 169 if traceFile := ctx.GlobalString(traceFlag.Name); traceFile != "" { 170 if err := Handler.StartGoTrace(traceFile); err != nil { 171 return err 172 } 173 } 174 175 if cpuFile := ctx.GlobalString(cpuprofileFlag.Name); cpuFile != "" { 176 if err := Handler.StartCPUProfile(cpuFile); err != nil { 177 return err 178 } 179 } 180 181 // pprof server 182 if ctx.GlobalBool(pprofFlag.Name) { 183 listenHost := ctx.GlobalString(pprofAddrFlag.Name) 184 185 port := ctx.GlobalInt(pprofPortFlag.Name) 186 187 address := fmt.Sprintf("%s:%d", listenHost, port) 188 StartPProf(address) 189 } 190 return nil 191 } 192 193 func StartPProf(address string) { 194 http.Handle("/memsize/", http.StripPrefix("/memsize", &Memsize)) 195 log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address)) 196 go func() { 197 if err := http.ListenAndServe(address, nil); err != nil { 198 log.Error("Failure in running pprof server", "err", err) 199 } 200 }() 201 } 202 203 // Exit stops all running profiles, flushing their output to the 204 // respective file. 205 func Exit() { 206 Handler.StopCPUProfile() 207 Handler.StopGoTrace() 208 }