github.com/aquanetwork/aquachain@v1.7.8/internal/debug/flags.go (about) 1 // Copyright 2016 The aquachain Authors 2 // This file is part of the aquachain library. 3 // 4 // The aquachain 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 aquachain 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 aquachain 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 colorable "github.com/mattn/go-colorable" 28 "gitlab.com/aquachain/aquachain/common/log" 29 "gitlab.com/aquachain/aquachain/common/log/term" 30 "gitlab.com/aquachain/aquachain/common/metrics" 31 "gitlab.com/aquachain/aquachain/common/metrics/exp" 32 "gopkg.in/urfave/cli.v1" 33 ) 34 35 var ( 36 verbosityFlag = cli.IntFlag{ 37 Name: "verbosity", 38 Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail", 39 Value: 3, 40 } 41 vmoduleFlag = cli.StringFlag{ 42 Name: "vmodule", 43 Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. aqua/*=5,p2p=4), try \"good\" or \"great\" for predefined verbose logging", 44 Value: "", 45 } 46 backtraceAtFlag = cli.StringFlag{ 47 Name: "backtrace", 48 Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")", 49 Value: "", 50 } 51 debugFlag = cli.BoolFlag{ 52 Name: "debug", 53 Usage: "Prepends log messages with call-site location (file and line number)", 54 } 55 pprofFlag = cli.BoolFlag{ 56 Name: "pprof", 57 Usage: "Enable the pprof HTTP server", 58 } 59 pprofPortFlag = cli.IntFlag{ 60 Name: "pprofport", 61 Usage: "pprof HTTP server listening port", 62 Value: 6060, 63 } 64 pprofAddrFlag = cli.StringFlag{ 65 Name: "pprofaddr", 66 Usage: "pprof HTTP server listening interface", 67 Value: "127.0.0.1", 68 } 69 memprofilerateFlag = cli.IntFlag{ 70 Name: "memprofilerate", 71 Usage: "Turn on memory profiling with the given rate", 72 Value: runtime.MemProfileRate, 73 } 74 blockprofilerateFlag = cli.IntFlag{ 75 Name: "blockprofilerate", 76 Usage: "Turn on block profiling with the given rate", 77 } 78 cpuprofileFlag = cli.StringFlag{ 79 Name: "cpuprofile", 80 Usage: "Write CPU profile to the given file", 81 } 82 traceFlag = cli.StringFlag{ 83 Name: "trace", 84 Usage: "Write execution trace to the given file", 85 } 86 ) 87 88 // Flags holds all command-line flags required for debugging. 89 var Flags = []cli.Flag{ 90 verbosityFlag, vmoduleFlag, backtraceAtFlag, debugFlag, 91 pprofFlag, pprofAddrFlag, pprofPortFlag, 92 memprofilerateFlag, blockprofilerateFlag, cpuprofileFlag, traceFlag, 93 } 94 95 var glogger *log.GlogHandler 96 97 func init() { 98 usecolor := term.IsTty(os.Stderr.Fd()) && os.Getenv("TERM") != "dumb" 99 output := io.Writer(os.Stderr) 100 if usecolor { 101 output = colorable.NewColorableStderr() 102 } 103 glogger = log.NewGlogHandler(log.StreamHandler(output, log.TerminalFormat(usecolor))) 104 } 105 106 // Setup initializes profiling and logging based on the CLI flags. 107 // It should be called as early as possible in the program. 108 func Setup(ctx *cli.Context) error { 109 // logging 110 log.PrintOrigins(ctx.GlobalBool(debugFlag.Name)) 111 glogger.Verbosity(log.Lvl(ctx.GlobalInt(verbosityFlag.Name))) 112 glogger.Vmodule(wrapVmodule(ctx.GlobalString(vmoduleFlag.Name))) 113 glogger.BacktraceAt(ctx.GlobalString(backtraceAtFlag.Name)) 114 log.Root().SetHandler(glogger) 115 116 // profiling, tracing 117 runtime.MemProfileRate = ctx.GlobalInt(memprofilerateFlag.Name) 118 Handler.SetBlockProfileRate(ctx.GlobalInt(blockprofilerateFlag.Name)) 119 if traceFile := ctx.GlobalString(traceFlag.Name); traceFile != "" { 120 if err := Handler.StartGoTrace(traceFile); err != nil { 121 return err 122 } 123 } 124 if cpuFile := ctx.GlobalString(cpuprofileFlag.Name); cpuFile != "" { 125 if err := Handler.StartCPUProfile(cpuFile); err != nil { 126 return err 127 } 128 } 129 130 // pprof server 131 if ctx.GlobalBool(pprofFlag.Name) { 132 // Hook go-metrics into expvar on any /debug/metrics request, load all vars 133 // from the registry into expvar, and execute regular expvar handler. 134 exp.Exp(metrics.DefaultRegistry) 135 136 address := fmt.Sprintf("%s:%d", ctx.GlobalString(pprofAddrFlag.Name), ctx.GlobalInt(pprofPortFlag.Name)) 137 go func() { 138 log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address)) 139 if err := http.ListenAndServe(address, nil); err != nil { 140 log.Error("Failure in running pprof server", "err", err) 141 } 142 }() 143 } 144 return nil 145 } 146 147 // Exit stops all running profiles, flushing their output to the 148 // respective file. 149 func Exit() { 150 Handler.StopCPUProfile() 151 Handler.StopGoTrace() 152 }