diff --git a/cmd/state/commands/root.go b/cmd/state/commands/root.go index 28ec17062b4065d8772301928a5ed7e15a00b4a3..71ae187fa3669c05b34ef8cf96316c95593eb498 100644 --- a/cmd/state/commands/root.go +++ b/cmd/state/commands/root.go @@ -4,27 +4,24 @@ import ( "context" "encoding/json" "fmt" - "io" "os" "os/signal" - "runtime/pprof" "syscall" "github.com/ledgerwatch/turbo-geth/cmd/utils" "github.com/ledgerwatch/turbo-geth/core" + "github.com/ledgerwatch/turbo-geth/internal/debug" "github.com/ledgerwatch/turbo-geth/log" "github.com/spf13/cobra" ) var ( - cpuprofile string - cpuProfileFile io.WriteCloser - genesisPath string - genesis *core.Genesis + genesisPath string + genesis *core.Genesis ) func init() { - rootCmd.PersistentFlags().StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile `file`") + utils.CobraFlags(rootCmd, append(debug.Flags, utils.MetricsEnabledFlag, utils.MetricsEnabledExpensiveFlag)) rootCmd.PersistentFlags().StringVar(&genesisPath, "genesis", "", "path to genesis.json file") } @@ -50,15 +47,17 @@ var rootCmd = &cobra.Command{ Use: "state", Short: "state is a utility for Stateless ethereum clients", PersistentPreRun: func(cmd *cobra.Command, args []string) { + if err := debug.SetupCobra(cmd); err != nil { + panic(err) + } + genesis = core.DefaultGenesisBlock() if genesisPath != "" { genesis = genesisFromFile(genesisPath) } - - startProfilingIfNeeded() }, PersistentPostRun: func(cmd *cobra.Command, args []string) { - stopProfilingIfNeeded() + debug.Exit() }, } @@ -82,29 +81,3 @@ func Execute() { os.Exit(1) } } - -func startProfilingIfNeeded() { - if cpuprofile != "" { - fmt.Println("starting CPU profiling") - cpuProfileFile, err := os.Create(cpuprofile) - if err != nil { - log.Error("could not create CPU profile", "error", err) - return - } - if err := pprof.StartCPUProfile(cpuProfileFile); err != nil { - log.Error("could not start CPU profile", "error", err) - return - } - } -} - -func stopProfilingIfNeeded() { - if cpuprofile != "" { - fmt.Println("stopping CPU profiling") - pprof.StopCPUProfile() - } - - if cpuProfileFile != nil { - cpuProfileFile.Close() - } -} diff --git a/cmd/state/commands/stateless.go b/cmd/state/commands/stateless.go index 55b8feb53fef0ce1055222dfc661109c228a4c76..3e078f769d4f24798d0c57d5a4b0192db3bd7073 100644 --- a/cmd/state/commands/stateless.go +++ b/cmd/state/commands/stateless.go @@ -53,7 +53,6 @@ var statelessCmd = &cobra.Command{ Use: "stateless", Short: "Stateless Ethereum prototype", RunE: func(cmd *cobra.Command, args []string) error { - createDb := func(path string) (ethdb.Database, error) { return ethdb.NewBoltDatabase(path) } diff --git a/cmd/state/main.go b/cmd/state/main.go index 0aa86c9fb48ca2000314e62cb65bdc1f7aa8c1ca..75de60a7f87748dd98cafa75405609dac30a41f1 100644 --- a/cmd/state/main.go +++ b/cmd/state/main.go @@ -1,38 +1,9 @@ package main import ( - "io" - "os" - "github.com/ledgerwatch/turbo-geth/cmd/state/commands" - "github.com/ledgerwatch/turbo-geth/log" - "github.com/mattn/go-colorable" - "github.com/mattn/go-isatty" - - "net/http" - //nolint:gosec - _ "net/http/pprof" ) func main() { - var ( - ostream log.Handler - glogger *log.GlogHandler - ) - - usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb" - output := io.Writer(os.Stderr) - if usecolor { - output = colorable.NewColorableStderr() - } - ostream = log.StreamHandler(output, log.TerminalFormat(usecolor)) - glogger = log.NewGlogHandler(ostream) - log.Root().SetHandler(glogger) - glogger.Verbosity(log.LvlInfo) - - go func() { - log.Info("HTTP", "error", http.ListenAndServe("localhost:6060", nil)) - }() - commands.Execute() } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index ef951d99076c3e5d8f295007eb3dc006adb627ee..6e7cb7439508995478c9313bfce8e3dc3c9c0056 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -32,6 +32,7 @@ import ( "text/template" "time" + pcsclite "github.com/gballet/go-libpcsclite" "github.com/ledgerwatch/turbo-geth/accounts" "github.com/ledgerwatch/turbo-geth/accounts/keystore" "github.com/ledgerwatch/turbo-geth/common" @@ -61,8 +62,7 @@ import ( "github.com/ledgerwatch/turbo-geth/p2p/netutil" "github.com/ledgerwatch/turbo-geth/params" "github.com/ledgerwatch/turbo-geth/rpc" - - pcsclite "github.com/gballet/go-libpcsclite" + "github.com/spf13/cobra" "github.com/urfave/cli" ) @@ -1794,3 +1794,19 @@ func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error return action(ctx) } } + +func CobraFlags(cmd *cobra.Command, urfaveCliFlags []cli.Flag) { + flags := cmd.PersistentFlags() + for _, flag := range urfaveCliFlags { + switch f := flag.(type) { + case cli.IntFlag: + flags.Int(f.Name, f.Value, f.Usage) + case cli.StringFlag: + flags.String(f.Name, f.Value, f.Usage) + case cli.BoolFlag: + flags.Bool(f.Name, false, f.Usage) + default: + panic(fmt.Errorf("unexpected type: %T", flag)) + } + } +} diff --git a/internal/debug/flags.go b/internal/debug/flags.go index ec3ae2e422b6c64a5d78d64eeaa983cf92975faa..c51d72ce22bb63a3a244776cc9b6d4dc2799f4e6 100644 --- a/internal/debug/flags.go +++ b/internal/debug/flags.go @@ -25,13 +25,15 @@ import ( "os/signal" "runtime" "syscall" + "time" + "github.com/fjl/memsize/memsizeui" "github.com/ledgerwatch/turbo-geth/log" "github.com/ledgerwatch/turbo-geth/metrics" "github.com/ledgerwatch/turbo-geth/metrics/exp" - "github.com/fjl/memsize/memsizeui" colorable "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" + "github.com/spf13/cobra" "github.com/urfave/cli" ) @@ -112,6 +114,100 @@ func init() { glogger = log.NewGlogHandler(ostream) } +func SetupCobra(cmd *cobra.Command) error { + flags := cmd.Flags() + dbg, err := flags.GetBool(debugFlag.Name) + if err != nil { + return err + } + lvl, err := flags.GetInt(verbosityFlag.Name) + if err != nil { + return err + } + + vmodule, err := flags.GetString(vmoduleFlag.Name) + if err != nil { + return err + } + backtrace, err := flags.GetString(backtraceAtFlag.Name) + if err != nil { + return err + } + + // logging + log.PrintOrigins(dbg) + glogger.Verbosity(log.Lvl(lvl)) + err = glogger.Vmodule(vmodule) + if err != nil { + return err + } + err = glogger.BacktraceAt(backtrace) + if err != nil { + return err + } + log.Root().SetHandler(glogger) + + memprofilerate, err := flags.GetInt(memprofilerateFlag.Name) + if err != nil { + return err + } + blockprofilerate, err := flags.GetInt(blockprofilerateFlag.Name) + if err != nil { + return err + } + traceFile, err := flags.GetString(traceFlag.Name) + if err != nil { + return err + } + cpuFile, err := flags.GetString(cpuprofileFlag.Name) + if err != nil { + return err + } + + // profiling, tracing + runtime.MemProfileRate = memprofilerate + Handler.SetBlockProfileRate(blockprofilerate) + if traceFile != "" { + if err2 := Handler.StartGoTrace(traceFile); err2 != nil { + return err2 + } + } + if cpuFile != "" { + if err2 := Handler.StartCPUProfile(cpuFile); err2 != nil { + return err2 + } + } + + go func() { + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + <-c + Exit() + }() + pprof, err := flags.GetBool(pprofFlag.Name) + if err != nil { + return err + } + pprofAddr, err := flags.GetString(pprofAddrFlag.Name) + if err != nil { + return err + } + pprofPort, err := flags.GetInt(pprofPortFlag.Name) + if err != nil { + return err + } + + // pprof server + if pprof { + StartPProf(fmt.Sprintf("%s:%d", pprofAddr, pprofPort)) + } + + // Start system runtime metrics collection + go metrics.CollectProcessMetrics(3 * time.Second) + + return nil +} + // Setup initializes profiling and logging based on the CLI flags. // It should be called as early as possible in the program. func Setup(ctx *cli.Context) error {