github.com/klaytn/klaytn@v1.10.2/api/debug/flags.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2016 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from internal/debug/flags.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package debug 22 23 import ( 24 "fmt" 25 "io" 26 _ "net/http/pprof" 27 "os" 28 "runtime" 29 30 "github.com/fjl/memsize/memsizeui" 31 "github.com/klaytn/klaytn/log" 32 "github.com/klaytn/klaytn/log/term" 33 colorable "github.com/mattn/go-colorable" 34 "gopkg.in/urfave/cli.v1" 35 "gopkg.in/urfave/cli.v1/altsrc" 36 ) 37 38 var Memsize memsizeui.Handler 39 40 var ( 41 verbosityFlag = cli.IntFlag{ 42 Name: "verbosity", 43 Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail", 44 Value: 3, 45 EnvVar: "KLAYTN_VERBOSITY", 46 } 47 vmoduleFlag = cli.StringFlag{ 48 Name: "vmodule", 49 Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. klay/*=5,p2p=4)", 50 Value: "", 51 EnvVar: "KLAYTN_VMODULE", 52 } 53 backtraceAtFlag = cli.StringFlag{ 54 Name: "backtrace", 55 Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")", 56 Value: "", 57 EnvVar: "KLAYTN_BACKTRACE", 58 } 59 debugFlag = cli.BoolFlag{ 60 Name: "debug", 61 Usage: "Prepends log messages with call-site location (file and line number)", 62 EnvVar: "KLAYTN_DEBUG", 63 } 64 pprofFlag = cli.BoolFlag{ 65 Name: "pprof", 66 Usage: "Enable the pprof HTTP server", 67 EnvVar: "KLAYTN_PPROF", 68 } 69 pprofPortFlag = cli.IntFlag{ 70 Name: "pprofport", 71 Usage: "pprof HTTP server listening port", 72 Value: 6060, 73 EnvVar: "KLAYTN_PPROFPORT", 74 } 75 pprofAddrFlag = cli.StringFlag{ 76 Name: "pprofaddr", 77 Usage: "pprof HTTP server listening interface", 78 Value: "127.0.0.1", 79 EnvVar: "KLAYTN_PPROFADDR", 80 } 81 memprofileFlag = cli.StringFlag{ 82 Name: "memprofile", 83 Usage: "Write memory profile to the given file", 84 EnvVar: "KLAYTN_MEMPROFILE", 85 } 86 memprofilerateFlag = cli.IntFlag{ 87 Name: "memprofilerate", 88 Usage: "Turn on memory profiling with the given rate", 89 Value: runtime.MemProfileRate, 90 EnvVar: "KLAYTN_MEMPROFILERATE", 91 } 92 blockprofilerateFlag = cli.IntFlag{ 93 Name: "blockprofilerate", 94 Usage: "Turn on block profiling with the given rate", 95 EnvVar: "KLAYTN_BLOCKPROFILERATE", 96 } 97 cpuprofileFlag = cli.StringFlag{ 98 Name: "cpuprofile", 99 Usage: "Write CPU profile to the given file", 100 EnvVar: "KLAYTN_CPUPROFILE", 101 } 102 traceFlag = cli.StringFlag{ 103 Name: "trace", 104 Usage: "Write execution trace to the given file", 105 EnvVar: "KLAYTN_TRACE", 106 } 107 ) 108 109 // Flags holds all command-line flags required for debugging. 110 var Flags = []cli.Flag{ 111 altsrc.NewIntFlag(verbosityFlag), 112 altsrc.NewStringFlag(vmoduleFlag), 113 altsrc.NewStringFlag(backtraceAtFlag), 114 altsrc.NewBoolFlag(debugFlag), 115 altsrc.NewBoolFlag(pprofFlag), 116 altsrc.NewStringFlag(pprofAddrFlag), 117 altsrc.NewIntFlag(pprofPortFlag), 118 altsrc.NewStringFlag(memprofileFlag), 119 altsrc.NewIntFlag(memprofilerateFlag), 120 altsrc.NewIntFlag(blockprofilerateFlag), 121 altsrc.NewStringFlag(cpuprofileFlag), 122 altsrc.NewStringFlag(traceFlag), 123 } 124 125 var glogger *log.GlogHandler 126 127 func init() { 128 usecolor := term.IsTty(os.Stderr.Fd()) && os.Getenv("TERM") != "dumb" 129 output := io.Writer(os.Stderr) 130 if usecolor { 131 output = colorable.NewColorableStderr() 132 } 133 glogger = log.NewGlogHandler(log.StreamHandler(output, log.TerminalFormat(usecolor))) 134 } 135 136 func GetGlogger() (*log.GlogHandler, error) { 137 if glogger != nil { 138 return glogger, nil 139 } 140 return nil, fmt.Errorf("glogger is nil") 141 } 142 143 // CreateLogDir creates a directory whose path is logdir as well as empty log files. 144 func CreateLogDir(logDir string) { 145 if logDir == "" { 146 return 147 } 148 Handler.logDir = logDir 149 150 // Currently failures on directory or file creation is treated as a warning. 151 if err := os.MkdirAll(logDir, 0o700); err != nil { 152 logger.Warn("Failed to create a directory", "logDir", logDir, "err", err) 153 } 154 } 155 156 // Setup initializes profiling and logging based on the CLI flags. 157 // It should be called as early as possible in the program. 158 func Setup(ctx *cli.Context) error { 159 // logging 160 log.PrintOrigins(ctx.GlobalBool(debugFlag.Name)) 161 if err := log.ChangeGlobalLogLevel(glogger, log.Lvl(ctx.GlobalInt(verbosityFlag.Name))); err != nil { 162 return err 163 } 164 if err := glogger.Vmodule(ctx.GlobalString(vmoduleFlag.Name)); err != nil { 165 return err 166 } 167 if len(ctx.GlobalString(backtraceAtFlag.Name)) != 0 { 168 if err := glogger.BacktraceAt(ctx.GlobalString(backtraceAtFlag.Name)); err != nil { 169 return err 170 } 171 } 172 log.Root().SetHandler(glogger) 173 174 // profiling, tracing 175 runtime.MemProfileRate = ctx.GlobalInt(memprofilerateFlag.Name) 176 Handler.SetBlockProfileRate(ctx.GlobalInt(blockprofilerateFlag.Name)) 177 if traceFile := ctx.GlobalString(traceFlag.Name); traceFile != "" { 178 if err := Handler.StartGoTrace(traceFile); err != nil { 179 return err 180 } 181 } 182 if cpuFile := ctx.GlobalString(cpuprofileFlag.Name); cpuFile != "" { 183 if err := Handler.StartCPUProfile(cpuFile); err != nil { 184 return err 185 } 186 } 187 Handler.memFile = ctx.GlobalString(memprofileFlag.Name) 188 189 // pprof server 190 if ctx.GlobalBool(pprofFlag.Name) { 191 addr := ctx.GlobalString(pprofAddrFlag.Name) 192 port := ctx.GlobalInt(pprofPortFlag.Name) 193 Handler.StartPProf(&addr, &port) 194 } 195 return nil 196 } 197 198 // Exit stops all running profiles, flushing their output to the 199 // respective file. 200 func Exit() { 201 if Handler.vmLogFile != nil { 202 Handler.vmLogFile.Close() 203 Handler.vmLogFile = nil 204 } 205 if Handler.memFile != "" { 206 Handler.WriteMemProfile(Handler.memFile) 207 } 208 Handler.StopCPUProfile() 209 Handler.StopGoTrace() 210 Handler.StopPProf() 211 }