github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/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/PlatONnetwork/PlatON-Go/log" 28 "github.com/PlatONnetwork/PlatON-Go/log/term" 29 "github.com/PlatONnetwork/PlatON-Go/metrics" 30 "github.com/PlatONnetwork/PlatON-Go/metrics/exp" 31 "github.com/fjl/memsize/memsizeui" 32 "github.com/mattn/go-colorable" 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 backtraceAtFlag = cli.StringFlag{ 50 Name: "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: "debug", 56 Usage: "Prepends log messages with call-site location (file and line number)", 57 } 58 59 pprofFlag = cli.BoolFlag{ 60 Name: "pprof", 61 Usage: "Enable the pprof HTTP server", 62 } 63 pprofPortFlag = cli.IntFlag{ 64 Name: "pprofport", 65 Usage: "pprof HTTP server listening port", 66 Value: 6060, 67 } 68 pprofAddrFlag = cli.StringFlag{ 69 Name: "pprofaddr", 70 Usage: "pprof HTTP server listening interface", 71 Value: "127.0.0.1", 72 } 73 memprofilerateFlag = cli.IntFlag{ 74 Name: "memprofilerate", 75 Usage: "Turn on memory profiling with the given rate", 76 Value: runtime.MemProfileRate, 77 } 78 blockprofilerateFlag = cli.IntFlag{ 79 Name: "blockprofilerate", 80 Usage: "Turn on block profiling with the given rate", 81 } 82 cpuprofileFlag = cli.StringFlag{ 83 Name: "cpuprofile", 84 Usage: "Write CPU profile to the given file", 85 } 86 traceFlag = cli.StringFlag{ 87 Name: "trace", 88 Usage: "Write execution trace to the given file", 89 } 90 91 wasmLogFileFlag = cli.StringFlag{ 92 Name: "wasmlog", 93 Usage: "output wasm contract log to file", 94 Value: "", 95 } 96 ) 97 98 // Flags holds all command-line flags required for debugging. 99 var Flags = []cli.Flag{ 100 verbosityFlag, vmoduleFlag, backtraceAtFlag, debugFlag, 101 pprofFlag, pprofAddrFlag, pprofPortFlag, 102 memprofilerateFlag, blockprofilerateFlag, cpuprofileFlag, traceFlag, 103 wasmLogFileFlag, 104 105 } 106 107 var ( 108 ostream log.Handler 109 glogger *log.GlogHandler 110 ) 111 112 func init() { 113 usecolor := term.IsTty(os.Stderr.Fd()) && os.Getenv("TERM") != "dumb" 114 output := io.Writer(os.Stderr) 115 if usecolor { 116 output = colorable.NewColorableStderr() 117 } 118 ostream = log.StreamHandler(output, log.TerminalFormat(usecolor)) 119 glogger = log.NewGlogHandler(ostream) 120 } 121 122 // Setup initializes profiling and logging based on the CLI flags. 123 // It should be called as early as possible in the program. 124 func Setup(ctx *cli.Context, logdir string) error { 125 // logging 126 log.PrintOrigins(ctx.GlobalBool(debugFlag.Name)) 127 if logdir != "" { 128 rfh, err := log.RotatingFileHandler( 129 logdir, 130 262144, 131 log.JSONFormatOrderedEx(false, true), 132 ) 133 if err != nil { 134 return err 135 } 136 glogger.SetHandler(log.MultiHandler(ostream, rfh)) 137 } 138 glogger.Verbosity(log.Lvl(ctx.GlobalInt(verbosityFlag.Name))) 139 glogger.Vmodule(ctx.GlobalString(vmoduleFlag.Name)) 140 glogger.BacktraceAt(ctx.GlobalString(backtraceAtFlag.Name)) 141 log.Root().SetHandler(glogger) 142 143 // profiling, tracing 144 runtime.MemProfileRate = ctx.GlobalInt(memprofilerateFlag.Name) 145 Handler.SetBlockProfileRate(ctx.GlobalInt(blockprofilerateFlag.Name)) 146 if traceFile := ctx.GlobalString(traceFlag.Name); traceFile != "" { 147 if err := Handler.StartGoTrace(traceFile); err != nil { 148 return err 149 } 150 } 151 if cpuFile := ctx.GlobalString(cpuprofileFlag.Name); cpuFile != "" { 152 if err := Handler.StartCPUProfile(cpuFile); err != nil { 153 return err 154 } 155 } 156 157 // pprof server 158 if ctx.GlobalBool(pprofFlag.Name) { 159 address := fmt.Sprintf("%s:%d", ctx.GlobalString(pprofAddrFlag.Name), ctx.GlobalInt(pprofPortFlag.Name)) 160 StartPProf(address) 161 } 162 return nil 163 } 164 165 func SetupWasmLog(ctx *cli.Context) error { 166 log.SetWasmLogLevel(log.Lvl(ctx.GlobalInt(verbosityFlag.Name))) 167 wasmFileName := ctx.GlobalString(wasmLogFileFlag.Name) 168 169 if wasmFileName == "" { 170 log.WasmRoot().SetHandler(log.Root().GetHandler()) 171 return nil 172 } 173 174 handler, err := log.FileHandler(wasmFileName, log.FormatFunc(func(r *log.Record) []byte { 175 return []byte(r.Msg) 176 })) 177 178 if err != nil { 179 return err 180 } 181 182 log.WasmRoot().SetHandler(handler) 183 184 return nil 185 } 186 187 func StartPProf(address string) { 188 // Hook go-metrics into expvar on any /debug/metrics request, load all vars 189 // from the registry into expvar, and execute regular expvar handler. 190 exp.Exp(metrics.DefaultRegistry) 191 http.Handle("/memsize/", http.StripPrefix("/memsize", &Memsize)) 192 log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address)) 193 go func() { 194 if err := http.ListenAndServe(address, nil); err != nil { 195 log.Error("Failure in running pprof server", "err", err) 196 } 197 }() 198 } 199 200 // Exit stops all running profiles, flushing their output to the 201 // respective file. 202 func Exit() { 203 Handler.StopCPUProfile() 204 Handler.StopGoTrace() 205 }