From 77374a92c6b21da26684b2dbb729f77a66a0af61 Mon Sep 17 00:00:00 2001 From: dvovk Date: Wed, 17 Apr 2024 15:40:21 +0100 Subject: [PATCH 01/14] wp --- turbo/app/diagnostics_cmd.go | 71 ++++++++++++++++++++++++++++++++++++ turbo/app/make_app.go | 1 + 2 files changed, 72 insertions(+) create mode 100644 turbo/app/diagnostics_cmd.go diff --git a/turbo/app/diagnostics_cmd.go b/turbo/app/diagnostics_cmd.go new file mode 100644 index 00000000000..fe545450c8b --- /dev/null +++ b/turbo/app/diagnostics_cmd.go @@ -0,0 +1,71 @@ +package app + +import ( + "fmt" + "io" + "net/http" + + "encoding/json" + + "github.com/ledgerwatch/erigon-lib/diagnostics" + "github.com/ledgerwatch/erigon/turbo/debug" + "github.com/ledgerwatch/log/v3" + "github.com/urfave/cli/v2" +) + +var ( + diagnosticsPrintDownloader = cli.StringFlag{ + Name: "diagnostics.print.downloader", + Usage: "Prints details about downloader status to console", + } +) + +var diagnosticsCommand = cli.Command{ + Action: MigrateFlags(printDiagnostics), + Name: "diagnostics", + Usage: "Print diagnostics data to console", + ArgsUsage: "--diagnostics.print.downloader", + Before: func(cliCtx *cli.Context) error { + _, _, err := debug.Setup(cliCtx, true /* rootLogger */) + if err != nil { + return err + } + return nil + }, + Flags: append([]cli.Flag{ + &diagnosticsPrintDownloader, + }, debug.Flags...), + + Description: `The diagnostics command prints diagnostics data to console.`, +} + +func printDiagnostics(cliCtx *cli.Context) error { + return PrintDiagnostics(cliCtx, log.Root()) +} + +func PrintDiagnostics(cliCtx *cli.Context, logger log.Logger) error { + logger.Info("[!!!!Starting diagnostics]") + MakeHttpGetCall() + return nil +} + +func MakeHttpGetCall() { + // Make a GET request + + resp, err := http.Get("http://localhost:6060/debug/snapshot-sync") + if err != nil { + fmt.Println("Error: ", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Println("Error: ", err) + } + + var data diagnostics.SyncStatistics + marshalErr := json.Unmarshal(body, &data) + if marshalErr == nil { + fmt.Println("current stage:", data.SyncStages.CurrentStage) + } + +} diff --git a/turbo/app/make_app.go b/turbo/app/make_app.go index a3e7af1a614..7b946bc5bb3 100644 --- a/turbo/app/make_app.go +++ b/turbo/app/make_app.go @@ -65,6 +65,7 @@ func MakeApp(name string, action cli.ActionFunc, cliFlags []cli.Flag) *cli.App { &importCommand, &snapshotCommand, &supportCommand, + &diagnosticsCommand, //&backupCommand, } return app From c6f1cd97934de6a737a553825daa281e9fbf3df5 Mon Sep 17 00:00:00 2001 From: dvovk Date: Fri, 19 Apr 2024 09:09:52 +0100 Subject: [PATCH 02/14] wp --- turbo/app/diagnostics_cmd.go | 63 ++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/turbo/app/diagnostics_cmd.go b/turbo/app/diagnostics_cmd.go index fe545450c8b..c0e2eb14d06 100644 --- a/turbo/app/diagnostics_cmd.go +++ b/turbo/app/diagnostics_cmd.go @@ -7,6 +7,7 @@ import ( "encoding/json" + "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon/turbo/debug" "github.com/ledgerwatch/log/v3" @@ -14,7 +15,7 @@ import ( ) var ( - diagnosticsPrintDownloader = cli.StringFlag{ + diagnosticsPrintDownloader = cli.BoolFlag{ Name: "diagnostics.print.downloader", Usage: "Prints details about downloader status to console", } @@ -24,7 +25,7 @@ var diagnosticsCommand = cli.Command{ Action: MigrateFlags(printDiagnostics), Name: "diagnostics", Usage: "Print diagnostics data to console", - ArgsUsage: "--diagnostics.print.downloader", + ArgsUsage: "--diagnostics.print.snapshot.download", Before: func(cliCtx *cli.Context) error { _, _, err := debug.Setup(cliCtx, true /* rootLogger */) if err != nil { @@ -65,7 +66,63 @@ func MakeHttpGetCall() { var data diagnostics.SyncStatistics marshalErr := json.Unmarshal(body, &data) if marshalErr == nil { - fmt.Println("current stage:", data.SyncStages.CurrentStage) + + /*fmt.Println("Current stage:", data.SyncStages.StagesList[data.SyncStages.CurrentStage]) + fmt.Println("Snapshot download progress:", data.SnapshotDownload.Downloaded) + fmt.Println("Snapshot download total:", data.SnapshotDownload.Total) + fmt.Println("Snapshot download speed:", data.SnapshotDownload.DownloadRate) + fmt.Println("Snapshot download time:", data.SnapshotDownload.TotalTime) + fmt.Println("Snapshot Upload speed:", data.SnapshotDownload.UploadRate) + fmt.Println("Peers count:", data.SnapshotDownload.Peers)*/ + + var remainingBytes uint64 + percent := 50 + if data.SnapshotDownload.Total > data.SnapshotDownload.Downloaded { + remainingBytes = data.SnapshotDownload.Total - data.SnapshotDownload.Downloaded + percent = int((data.SnapshotDownload.Downloaded*100)/data.SnapshotDownload.Total) / 2 + } + + logstr := "[" + + for i := 1; i < 50; i++ { + if i < percent { + logstr += "#" + } else { + logstr += "." + } + } + + logstr += "]" + + fmt.Println("Download:", logstr, common.ByteCount(data.SnapshotDownload.Downloaded), "/", common.ByteCount(data.SnapshotDownload.Total)) + downloadTimeLeft := calculateTime(remainingBytes, data.SnapshotDownload.DownloadRate) + + fmt.Println("Time left:", downloadTimeLeft) + + /*log.Info(fmt.Sprintf("[%s] %s", logPrefix, logReason), + "progress", fmt.Sprintf("%.2f%% %s/%s", stats.Progress, common.ByteCount(stats.BytesCompleted), common.ByteCount(stats.BytesTotal)), + "time-left", downloadTimeLeft, + "total-time", time.Since(startTime).Round(time.Second).String(), + "download", common.ByteCount(stats.DownloadRate)+"/s", + "upload", common.ByteCount(stats.UploadRate)+"/s", + "peers", stats.PeersUnique, + "files", stats.FilesTotal, + "metadata", fmt.Sprintf("%d/%d", stats.MetadataReady, stats.FilesTotal), + "connections", stats.ConnectionsTotal, + "alloc", common.ByteCount(m.Alloc), "sys", common.ByteCount(m.Sys), + )*/ } } + +func calculateTime(amountLeft, rate uint64) string { + if rate == 0 { + return "999hrs:99m" + } + timeLeftInSeconds := amountLeft / rate + + hours := timeLeftInSeconds / 3600 + minutes := (timeLeftInSeconds / 60) % 60 + + return fmt.Sprintf("%dhrs:%dm", hours, minutes) +} From 0c1a9634f4d7a67ddd9a2269fc6fefa10b9eecdd Mon Sep 17 00:00:00 2001 From: dvovk Date: Fri, 19 Apr 2024 13:32:56 +0100 Subject: [PATCH 03/14] updated logs --- turbo/app/diagnostics_cmd.go | 142 ++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 53 deletions(-) diff --git a/turbo/app/diagnostics_cmd.go b/turbo/app/diagnostics_cmd.go index c0e2eb14d06..ff19fae8646 100644 --- a/turbo/app/diagnostics_cmd.go +++ b/turbo/app/diagnostics_cmd.go @@ -1,6 +1,7 @@ package app import ( + "errors" "fmt" "io" "net/http" @@ -19,6 +20,13 @@ var ( Name: "diagnostics.print.downloader", Usage: "Prints details about downloader status to console", } + + debugURLFlag = cli.StringFlag{ + Name: "debug.addr", + Usage: "URL to the debug endpoint", + Required: false, + Value: "localhost:6060", + } ) var diagnosticsCommand = cli.Command{ @@ -35,6 +43,7 @@ var diagnosticsCommand = cli.Command{ }, Flags: append([]cli.Flag{ &diagnosticsPrintDownloader, + &debugURLFlag, }, debug.Flags...), Description: `The diagnostics command prints diagnostics data to console.`, @@ -45,74 +54,101 @@ func printDiagnostics(cliCtx *cli.Context) error { } func PrintDiagnostics(cliCtx *cli.Context, logger log.Logger) error { - logger.Info("[!!!!Starting diagnostics]") - MakeHttpGetCall() + url := "http://" + cliCtx.String(debugURLFlag.Name) + "/debug/" + PrintCurentStage(url) + PrintSnapshotDownload(url) return nil } -func MakeHttpGetCall() { - // Make a GET request +func PrintCurentStage(url string) { + data, err := GetSyncStats(url) + if err != nil { + log.Error("Error:", err) + return + } + + fmt.Println("-------------------Stages-------------------") + + for idx, stage := range data.SyncStages.StagesList { + if idx == int(data.SyncStages.CurrentStage) { + fmt.Println("[" + stage + "]" + " - Running") + } else if idx < int(data.SyncStages.CurrentStage) { + fmt.Println("[" + stage + "]" + " - Completed") + } else { + fmt.Println("[" + stage + "]" + " - Queued") + } + } +} - resp, err := http.Get("http://localhost:6060/debug/snapshot-sync") +func GetSyncStats(url string) (diagnostics.SyncStatistics, error) { + data, err := MakeHttpGetCall(url + "snapshot-sync") if err != nil { - fmt.Println("Error: ", err) + return diagnostics.SyncStatistics{}, err } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) + + if myValue, ok := data.(diagnostics.SyncStatistics); ok { + return myValue, nil + } else { + return diagnostics.SyncStatistics{}, errors.New("conversion failed: interface is not of type sync statistics") + } +} + +func PrintSnapshotDownload(url string) { + data, err := GetSyncStats(url) if err != nil { - fmt.Println("Error: ", err) + log.Error("Error:", err) + return } - var data diagnostics.SyncStatistics - marshalErr := json.Unmarshal(body, &data) - if marshalErr == nil { - - /*fmt.Println("Current stage:", data.SyncStages.StagesList[data.SyncStages.CurrentStage]) - fmt.Println("Snapshot download progress:", data.SnapshotDownload.Downloaded) - fmt.Println("Snapshot download total:", data.SnapshotDownload.Total) - fmt.Println("Snapshot download speed:", data.SnapshotDownload.DownloadRate) - fmt.Println("Snapshot download time:", data.SnapshotDownload.TotalTime) - fmt.Println("Snapshot Upload speed:", data.SnapshotDownload.UploadRate) - fmt.Println("Peers count:", data.SnapshotDownload.Peers)*/ - - var remainingBytes uint64 - percent := 50 - if data.SnapshotDownload.Total > data.SnapshotDownload.Downloaded { - remainingBytes = data.SnapshotDownload.Total - data.SnapshotDownload.Downloaded - percent = int((data.SnapshotDownload.Downloaded*100)/data.SnapshotDownload.Total) / 2 - } + fmt.Println("-------------------Snapshot Download-------------------") - logstr := "[" + snapDownload := data.SnapshotDownload + var remainingBytes uint64 + percent := 50 + if snapDownload.Total > snapDownload.Downloaded { + remainingBytes = snapDownload.Total - snapDownload.Downloaded + percent = int((snapDownload.Downloaded*100)/snapDownload.Total) / 2 + } - for i := 1; i < 50; i++ { - if i < percent { - logstr += "#" - } else { - logstr += "." - } + logstr := "[" + + for i := 1; i < 50; i++ { + if i < percent { + logstr += "#" + } else { + logstr += "." } + } + + logstr += "]" + + fmt.Println("Download:", logstr, common.ByteCount(snapDownload.Downloaded), "/", common.ByteCount(snapDownload.Total)) + downloadTimeLeft := calculateTime(remainingBytes, snapDownload.DownloadRate) + + fmt.Println("Time left:", downloadTimeLeft) +} + +func MakeHttpGetCall(url string) (any, error) { + // Make a GET request + + resp, err := http.Get(url) + if err != nil { + return nil, err + } - logstr += "]" - - fmt.Println("Download:", logstr, common.ByteCount(data.SnapshotDownload.Downloaded), "/", common.ByteCount(data.SnapshotDownload.Total)) - downloadTimeLeft := calculateTime(remainingBytes, data.SnapshotDownload.DownloadRate) - - fmt.Println("Time left:", downloadTimeLeft) - - /*log.Info(fmt.Sprintf("[%s] %s", logPrefix, logReason), - "progress", fmt.Sprintf("%.2f%% %s/%s", stats.Progress, common.ByteCount(stats.BytesCompleted), common.ByteCount(stats.BytesTotal)), - "time-left", downloadTimeLeft, - "total-time", time.Since(startTime).Round(time.Second).String(), - "download", common.ByteCount(stats.DownloadRate)+"/s", - "upload", common.ByteCount(stats.UploadRate)+"/s", - "peers", stats.PeersUnique, - "files", stats.FilesTotal, - "metadata", fmt.Sprintf("%d/%d", stats.MetadataReady, stats.FilesTotal), - "connections", stats.ConnectionsTotal, - "alloc", common.ByteCount(m.Alloc), "sys", common.ByteCount(m.Sys), - )*/ + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var data diagnostics.SyncStatistics + err = json.Unmarshal(body, &data) + if err != nil { + return nil, err } + return data, nil } func calculateTime(amountLeft, rate uint64) string { From 60d95dc08a5e7514084bb03e7005abb699bdcd4e Mon Sep 17 00:00:00 2001 From: dvovk Date: Fri, 19 Apr 2024 13:39:22 +0100 Subject: [PATCH 04/14] inital version done --- turbo/app/diagnostics_cmd.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/turbo/app/diagnostics_cmd.go b/turbo/app/diagnostics_cmd.go index ff19fae8646..8380000fa9d 100644 --- a/turbo/app/diagnostics_cmd.go +++ b/turbo/app/diagnostics_cmd.go @@ -17,7 +17,7 @@ import ( var ( diagnosticsPrintDownloader = cli.BoolFlag{ - Name: "diagnostics.print.downloader", + Name: "print.downloader", Usage: "Prints details about downloader status to console", } @@ -33,7 +33,7 @@ var diagnosticsCommand = cli.Command{ Action: MigrateFlags(printDiagnostics), Name: "diagnostics", Usage: "Print diagnostics data to console", - ArgsUsage: "--diagnostics.print.snapshot.download", + ArgsUsage: "--print.downloader", Before: func(cliCtx *cli.Context) error { _, _, err := debug.Setup(cliCtx, true /* rootLogger */) if err != nil { @@ -56,7 +56,10 @@ func printDiagnostics(cliCtx *cli.Context) error { func PrintDiagnostics(cliCtx *cli.Context, logger log.Logger) error { url := "http://" + cliCtx.String(debugURLFlag.Name) + "/debug/" PrintCurentStage(url) - PrintSnapshotDownload(url) + if cliCtx.Bool(diagnosticsPrintDownloader.Name) { + PrintSnapshotDownload(url) + } + return nil } @@ -129,8 +132,6 @@ func PrintSnapshotDownload(url string) { } func MakeHttpGetCall(url string) (any, error) { - // Make a GET request - resp, err := http.Get(url) if err != nil { return nil, err From 289ecfd7f4b05c8e1d94408e4e1fdcc109f36f57 Mon Sep 17 00:00:00 2001 From: Mark Holt Date: Sat, 20 Apr 2024 20:40:18 +0100 Subject: [PATCH 05/14] added diag command - needs testing --- cmd/diag/downloader/downloader.go | 77 ++++++++++++++++++++++ cmd/diag/flags/flags.go | 21 ++++++ cmd/diag/main.go | 105 ++++++++++++++++++++++++++++++ cmd/diag/stages/stages.go | 60 +++++++++++++++++ cmd/diag/util/util.go | 40 ++++++++++++ 5 files changed, 303 insertions(+) create mode 100644 cmd/diag/downloader/downloader.go create mode 100644 cmd/diag/flags/flags.go create mode 100644 cmd/diag/main.go create mode 100644 cmd/diag/stages/stages.go create mode 100644 cmd/diag/util/util.go diff --git a/cmd/diag/downloader/downloader.go b/cmd/diag/downloader/downloader.go new file mode 100644 index 00000000000..5a06f58a276 --- /dev/null +++ b/cmd/diag/downloader/downloader.go @@ -0,0 +1,77 @@ +package downloader + +import ( + "encoding/json" + "fmt" + + "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon-lib/diagnostics" + "github.com/ledgerwatch/erigon/cmd/diag/flags" + "github.com/ledgerwatch/erigon/cmd/diag/util" + "github.com/urfave/cli/v2" +) + +var Command = cli.Command{ + Action: print, + Name: "downloader", + Aliases: []string{"dl"}, + Usage: "print snapshot download stats", + ArgsUsage: "", + Flags: []cli.Flag{ + &flags.DebugURLFlag, + &flags.OutputFlag, + }, + Description: ``, +} + +func print(cliCtx *cli.Context) error { + var data diagnostics.SyncStatistics + url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/" + + err := util.MakeHttpGetCall(url, data) + + if err != nil { + return err + } + + switch cliCtx.String(flags.OutputFlag.Name) { + case "json": + bytes, err := json.Marshal(data.SnapshotDownload) + + if err != nil { + return err + } + + fmt.Println(string(bytes)) + + case "text": + fmt.Println("-------------------Snapshot Download-------------------") + + snapDownload := data.SnapshotDownload + var remainingBytes uint64 + percent := 50 + if snapDownload.Total > snapDownload.Downloaded { + remainingBytes = snapDownload.Total - snapDownload.Downloaded + percent = int((snapDownload.Downloaded*100)/snapDownload.Total) / 2 + } + + logstr := "[" + + for i := 1; i < 50; i++ { + if i < percent { + logstr += "#" + } else { + logstr += "." + } + } + + logstr += "]" + + fmt.Println("Download:", logstr, common.ByteCount(snapDownload.Downloaded), "/", common.ByteCount(snapDownload.Total)) + downloadTimeLeft := util.CalculateTime(remainingBytes, snapDownload.DownloadRate) + + fmt.Println("Time left:", downloadTimeLeft) + } + + return nil +} diff --git a/cmd/diag/flags/flags.go b/cmd/diag/flags/flags.go new file mode 100644 index 00000000000..a172bfb3f3e --- /dev/null +++ b/cmd/diag/flags/flags.go @@ -0,0 +1,21 @@ +package flags + +import "github.com/urfave/cli/v2" + +var ( + DebugURLFlag = cli.StringFlag{ + Name: "debug.addr", + Aliases: []string{"da"}, + Usage: "URL to the debug endpoint", + Required: false, + Value: "localhost:6060", + } + + OutputFlag = cli.StringFlag{ + Name: "output", + Aliases: []string{"o"}, + Usage: "Output format [text|json]", + Required: false, + Value: "text", + } +) diff --git a/cmd/diag/main.go b/cmd/diag/main.go new file mode 100644 index 00000000000..bd0d60293f2 --- /dev/null +++ b/cmd/diag/main.go @@ -0,0 +1,105 @@ +package main + +import ( + "context" + "fmt" + "os" + "os/signal" + "path/filepath" + "syscall" + + "github.com/ledgerwatch/log/v3" + "github.com/urfave/cli/v2" + + "github.com/ledgerwatch/erigon/cmd/diag/downloader" + "github.com/ledgerwatch/erigon/cmd/diag/stages" + "github.com/ledgerwatch/erigon/cmd/snapshots/sync" + "github.com/ledgerwatch/erigon/cmd/utils" + "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/turbo/logging" +) + +func main() { + logging.LogVerbosityFlag.Value = log.LvlError.String() + logging.LogConsoleVerbosityFlag.Value = log.LvlError.String() + + app := cli.NewApp() + app.Name = "diagnostics" + app.Version = params.VersionWithCommit(params.GitCommit) + app.EnableBashCompletion = true + + app.Commands = []*cli.Command{ + &downloader.Command, + &stages.Command, + } + + app.Flags = []cli.Flag{} + + app.UsageText = app.Name + ` [command] [flags]` + + app.Action = func(context *cli.Context) error { + if context.Args().Present() { + var goodNames []string + for _, c := range app.VisibleCommands() { + goodNames = append(goodNames, c.Name) + } + _, _ = fmt.Fprintf(os.Stderr, "Command '%s' not found. Available commands: %s\n", context.Args().First(), goodNames) + cli.ShowAppHelpAndExit(context, 1) + } + + return nil + } + + for _, command := range app.Commands { + command.Before = func(ctx *cli.Context) error { + logger, err := setupLogger(ctx) + + if err != nil { + return err + } + + var cancel context.CancelFunc + + ctx.Context, cancel = context.WithCancel(sync.WithLogger(ctx.Context, logger)) + + go handleTerminationSignals(cancel, logger) + + return nil + } + } + + if err := app.Run(os.Args); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func setupLogger(ctx *cli.Context) (log.Logger, error) { + dataDir := ctx.String(utils.DataDirFlag.Name) + + if len(dataDir) > 0 { + logsDir := filepath.Join(dataDir, "logs") + + if err := os.MkdirAll(logsDir, 0755); err != nil { + return nil, err + } + } + + logger := logging.SetupLoggerCtx("diagnostics-"+ctx.Command.Name, ctx, log.LvlError, log.LvlInfo, false) + + return logger, nil +} + +func handleTerminationSignals(stopFunc func(), logger log.Logger) { + signalCh := make(chan os.Signal, 1) + signal.Notify(signalCh, syscall.SIGTERM, syscall.SIGINT) + + switch s := <-signalCh; s { + case syscall.SIGTERM: + logger.Info("Stopping") + stopFunc() + case syscall.SIGINT: + logger.Info("Terminating") + os.Exit(-int(syscall.SIGINT)) + } +} diff --git a/cmd/diag/stages/stages.go b/cmd/diag/stages/stages.go new file mode 100644 index 00000000000..fc5446cc9cf --- /dev/null +++ b/cmd/diag/stages/stages.go @@ -0,0 +1,60 @@ +package stages + +import ( + "fmt" + + "github.com/ledgerwatch/erigon-lib/diagnostics" + "github.com/ledgerwatch/erigon/cmd/diag/flags" + "github.com/ledgerwatch/erigon/cmd/diag/util" + "github.com/urfave/cli/v2" +) + +var Command = cli.Command{ + Name: "states", + Aliases: []string{"st"}, + ArgsUsage: "", + Subcommands: []*cli.Command{ + { + Name: "current", + Aliases: []string{"c"}, + Action: printCurentStage, + Usage: "print current state", + ArgsUsage: "", + Flags: []cli.Flag{ + &flags.DebugURLFlag, + &flags.OutputFlag, + }, + }, + }, + Description: ``, +} + +func printCurentStage(cliCtx *cli.Context) error { + var data diagnostics.SyncStatistics + url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/" + + err := util.MakeHttpGetCall(url, data) + + if err != nil { + return err + } + + switch cliCtx.String(flags.OutputFlag.Name) { + case "json": + + case "text": + fmt.Println("-------------------Stages-------------------") + + for idx, stage := range data.SyncStages.StagesList { + if idx == int(data.SyncStages.CurrentStage) { + fmt.Println("[" + stage + "]" + " - Running") + } else if idx < int(data.SyncStages.CurrentStage) { + fmt.Println("[" + stage + "]" + " - Completed") + } else { + fmt.Println("[" + stage + "]" + " - Queued") + } + } + } + + return nil +} diff --git a/cmd/diag/util/util.go b/cmd/diag/util/util.go new file mode 100644 index 00000000000..c223ab99cdc --- /dev/null +++ b/cmd/diag/util/util.go @@ -0,0 +1,40 @@ +package util + +import ( + "encoding/json" + "fmt" + "io" + "net/http" +) + +func MakeHttpGetCall(url string, data interface{}) error { + resp, err := http.Get(url) + if err != nil { + return err + } + + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + err = json.Unmarshal(body, data) + if err != nil { + return err + } + + return nil +} + +func CalculateTime(amountLeft, rate uint64) string { + if rate == 0 { + return "999hrs:99m" + } + timeLeftInSeconds := amountLeft / rate + + hours := timeLeftInSeconds / 3600 + minutes := (timeLeftInSeconds / 60) % 60 + + return fmt.Sprintf("%dhrs:%dm", hours, minutes) +} From 4d807848345bfe7e4b9d4dda5babf265c4c61122 Mon Sep 17 00:00:00 2001 From: Mark Holt Date: Sun, 21 Apr 2024 11:06:02 +0100 Subject: [PATCH 06/14] initial tests runing --- cmd/diag/downloader/downloader.go | 2 +- cmd/diag/stages/stages.go | 14 ++++++++++---- cmd/diag/util/util.go | 15 +++++++++++++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/cmd/diag/downloader/downloader.go b/cmd/diag/downloader/downloader.go index 5a06f58a276..cd341e8afbb 100644 --- a/cmd/diag/downloader/downloader.go +++ b/cmd/diag/downloader/downloader.go @@ -28,7 +28,7 @@ func print(cliCtx *cli.Context) error { var data diagnostics.SyncStatistics url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/" - err := util.MakeHttpGetCall(url, data) + err := util.MakeHttpGetCall(cliCtx.Context, url, data) if err != nil { return err diff --git a/cmd/diag/stages/stages.go b/cmd/diag/stages/stages.go index fc5446cc9cf..9dc2830faa7 100644 --- a/cmd/diag/stages/stages.go +++ b/cmd/diag/stages/stages.go @@ -1,6 +1,7 @@ package stages import ( + "encoding/json" "fmt" "github.com/ledgerwatch/erigon-lib/diagnostics" @@ -10,7 +11,7 @@ import ( ) var Command = cli.Command{ - Name: "states", + Name: "stages", Aliases: []string{"st"}, ArgsUsage: "", Subcommands: []*cli.Command{ @@ -18,7 +19,7 @@ var Command = cli.Command{ Name: "current", Aliases: []string{"c"}, Action: printCurentStage, - Usage: "print current state", + Usage: "print current stage", ArgsUsage: "", Flags: []cli.Flag{ &flags.DebugURLFlag, @@ -33,14 +34,19 @@ func printCurentStage(cliCtx *cli.Context) error { var data diagnostics.SyncStatistics url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/" - err := util.MakeHttpGetCall(url, data) - + err := util.MakeHttpGetCall(cliCtx.Context, url, data) if err != nil { return err } switch cliCtx.String(flags.OutputFlag.Name) { case "json": + bytes, err := json.Marshal(data.SyncStages.StagesList) + if err != nil { + return err + } + + fmt.Println(string(bytes)) case "text": fmt.Println("-------------------Stages-------------------") diff --git a/cmd/diag/util/util.go b/cmd/diag/util/util.go index c223ab99cdc..f67df28c34b 100644 --- a/cmd/diag/util/util.go +++ b/cmd/diag/util/util.go @@ -1,14 +1,25 @@ package util import ( + "context" "encoding/json" "fmt" "io" "net/http" + "time" ) -func MakeHttpGetCall(url string, data interface{}) error { - resp, err := http.Get(url) +func MakeHttpGetCall(ctx context.Context, url string, data interface{}) error { + var client = &http.Client{ + Timeout: time.Second * 20, + } + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return err + } + + resp, err := client.Do(req) if err != nil { return err } From aabb646a236649c854ede18bb6bac5b90666c2be Mon Sep 17 00:00:00 2001 From: Mark Holt Date: Sun, 21 Apr 2024 15:30:38 +0100 Subject: [PATCH 07/14] added cmd to makefile --- Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ebc5081ac32..a0039c155ec 100644 --- a/Makefile +++ b/Makefile @@ -135,9 +135,7 @@ COMMANDS += evm COMMANDS += sentinel COMMANDS += caplin COMMANDS += snapshots - - - +COMMANDS += diag # build each command using %.cmd rule $(COMMANDS): %: %.cmd From f3a9bbaf4570aae4ecac55ce55e297e3d0cd69b7 Mon Sep 17 00:00:00 2001 From: Mark Holt Date: Sun, 21 Apr 2024 15:59:54 +0100 Subject: [PATCH 08/14] show help if no command --- cmd/diag/main.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/cmd/diag/main.go b/cmd/diag/main.go index bd0d60293f2..f619edc02e9 100644 --- a/cmd/diag/main.go +++ b/cmd/diag/main.go @@ -24,7 +24,7 @@ func main() { logging.LogConsoleVerbosityFlag.Value = log.LvlError.String() app := cli.NewApp() - app.Name = "diagnostics" + app.Name = "diag" app.Version = params.VersionWithCommit(params.GitCommit) app.EnableBashCompletion = true @@ -38,14 +38,12 @@ func main() { app.UsageText = app.Name + ` [command] [flags]` app.Action = func(context *cli.Context) error { - if context.Args().Present() { - var goodNames []string - for _, c := range app.VisibleCommands() { - goodNames = append(goodNames, c.Name) - } - _, _ = fmt.Fprintf(os.Stderr, "Command '%s' not found. Available commands: %s\n", context.Args().First(), goodNames) - cli.ShowAppHelpAndExit(context, 1) + var goodNames []string + for _, c := range app.VisibleCommands() { + goodNames = append(goodNames, c.Name) } + _, _ = fmt.Fprintf(os.Stderr, "Command '%s' not found. Available commands: %s\n", context.Args().First(), goodNames) + cli.ShowAppHelpAndExit(context, 1) return nil } From a9a25586b4ec12df7a9bf7bffa9f43ddd82a9540 Mon Sep 17 00:00:00 2001 From: Mark Holt Date: Sun, 21 Apr 2024 16:45:26 +0100 Subject: [PATCH 09/14] fix usage --- cmd/diag/main.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/diag/main.go b/cmd/diag/main.go index f619edc02e9..527e7251613 100644 --- a/cmd/diag/main.go +++ b/cmd/diag/main.go @@ -24,7 +24,7 @@ func main() { logging.LogConsoleVerbosityFlag.Value = log.LvlError.String() app := cli.NewApp() - app.Name = "diag" + app.Name = "diagnostics" app.Version = params.VersionWithCommit(params.GitCommit) app.EnableBashCompletion = true @@ -35,7 +35,8 @@ func main() { app.Flags = []cli.Flag{} - app.UsageText = app.Name + ` [command] [flags]` + app.HelpName = `erigon diagnostics` + app.UsageText = `diag [command] [flags]` app.Action = func(context *cli.Context) error { var goodNames []string From 5a0cbc9a9ca557cc03b31384de2afeaeddc5ed21 Mon Sep 17 00:00:00 2001 From: dvovk Date: Sun, 21 Apr 2024 17:54:24 +0100 Subject: [PATCH 10/14] updated endpoints --- cmd/diag/downloader/downloader.go | 2 +- cmd/diag/stages/stages.go | 2 +- cmd/diag/util/util.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/diag/downloader/downloader.go b/cmd/diag/downloader/downloader.go index cd341e8afbb..1b58105d2e0 100644 --- a/cmd/diag/downloader/downloader.go +++ b/cmd/diag/downloader/downloader.go @@ -26,7 +26,7 @@ var Command = cli.Command{ func print(cliCtx *cli.Context) error { var data diagnostics.SyncStatistics - url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/" + url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/snapshot-sync" err := util.MakeHttpGetCall(cliCtx.Context, url, data) diff --git a/cmd/diag/stages/stages.go b/cmd/diag/stages/stages.go index 9dc2830faa7..a322a735165 100644 --- a/cmd/diag/stages/stages.go +++ b/cmd/diag/stages/stages.go @@ -32,7 +32,7 @@ var Command = cli.Command{ func printCurentStage(cliCtx *cli.Context) error { var data diagnostics.SyncStatistics - url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/" + url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/snapshot-sync" err := util.MakeHttpGetCall(cliCtx.Context, url, data) if err != nil { diff --git a/cmd/diag/util/util.go b/cmd/diag/util/util.go index f67df28c34b..f6c9e6184e2 100644 --- a/cmd/diag/util/util.go +++ b/cmd/diag/util/util.go @@ -30,7 +30,7 @@ func MakeHttpGetCall(ctx context.Context, url string, data interface{}) error { return err } - err = json.Unmarshal(body, data) + err = json.Unmarshal(body, &data) if err != nil { return err } From 4f1f57558a6e7db28acaf80e473ab9c09a623482 Mon Sep 17 00:00:00 2001 From: dvovk Date: Sun, 21 Apr 2024 18:11:22 +0100 Subject: [PATCH 11/14] fixed unmarshal --- cmd/diag/downloader/downloader.go | 2 +- cmd/diag/stages/stages.go | 2 +- cmd/diag/util/util.go | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/diag/downloader/downloader.go b/cmd/diag/downloader/downloader.go index 1b58105d2e0..af3350e4b70 100644 --- a/cmd/diag/downloader/downloader.go +++ b/cmd/diag/downloader/downloader.go @@ -28,7 +28,7 @@ func print(cliCtx *cli.Context) error { var data diagnostics.SyncStatistics url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/snapshot-sync" - err := util.MakeHttpGetCall(cliCtx.Context, url, data) + err := util.MakeHttpGetCall(cliCtx.Context, url, &data) if err != nil { return err diff --git a/cmd/diag/stages/stages.go b/cmd/diag/stages/stages.go index a322a735165..9837de2f041 100644 --- a/cmd/diag/stages/stages.go +++ b/cmd/diag/stages/stages.go @@ -34,7 +34,7 @@ func printCurentStage(cliCtx *cli.Context) error { var data diagnostics.SyncStatistics url := "http://" + cliCtx.String(flags.DebugURLFlag.Name) + "/debug/snapshot-sync" - err := util.MakeHttpGetCall(cliCtx.Context, url, data) + err := util.MakeHttpGetCall(cliCtx.Context, url, &data) if err != nil { return err } diff --git a/cmd/diag/util/util.go b/cmd/diag/util/util.go index f6c9e6184e2..a2ec9008221 100644 --- a/cmd/diag/util/util.go +++ b/cmd/diag/util/util.go @@ -7,6 +7,8 @@ import ( "io" "net/http" "time" + + "github.com/ledgerwatch/erigon-lib/diagnostics" ) func MakeHttpGetCall(ctx context.Context, url string, data interface{}) error { @@ -30,6 +32,12 @@ func MakeHttpGetCall(ctx context.Context, url string, data interface{}) error { return err } + var dataaaa diagnostics.SyncStatistics + numerr := json.Unmarshal(body, &dataaaa) + if numerr != nil { + return numerr + } + err = json.Unmarshal(body, &data) if err != nil { return err From ebb5332433c8edc2a2c0a26014b93f79db4c699f Mon Sep 17 00:00:00 2001 From: dvovk Date: Sun, 21 Apr 2024 18:12:14 +0100 Subject: [PATCH 12/14] removed turbo app --- turbo/app/diagnostics_cmd.go | 165 ----------------------------------- turbo/app/make_app.go | 1 - 2 files changed, 166 deletions(-) delete mode 100644 turbo/app/diagnostics_cmd.go diff --git a/turbo/app/diagnostics_cmd.go b/turbo/app/diagnostics_cmd.go deleted file mode 100644 index 8380000fa9d..00000000000 --- a/turbo/app/diagnostics_cmd.go +++ /dev/null @@ -1,165 +0,0 @@ -package app - -import ( - "errors" - "fmt" - "io" - "net/http" - - "encoding/json" - - "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon-lib/diagnostics" - "github.com/ledgerwatch/erigon/turbo/debug" - "github.com/ledgerwatch/log/v3" - "github.com/urfave/cli/v2" -) - -var ( - diagnosticsPrintDownloader = cli.BoolFlag{ - Name: "print.downloader", - Usage: "Prints details about downloader status to console", - } - - debugURLFlag = cli.StringFlag{ - Name: "debug.addr", - Usage: "URL to the debug endpoint", - Required: false, - Value: "localhost:6060", - } -) - -var diagnosticsCommand = cli.Command{ - Action: MigrateFlags(printDiagnostics), - Name: "diagnostics", - Usage: "Print diagnostics data to console", - ArgsUsage: "--print.downloader", - Before: func(cliCtx *cli.Context) error { - _, _, err := debug.Setup(cliCtx, true /* rootLogger */) - if err != nil { - return err - } - return nil - }, - Flags: append([]cli.Flag{ - &diagnosticsPrintDownloader, - &debugURLFlag, - }, debug.Flags...), - - Description: `The diagnostics command prints diagnostics data to console.`, -} - -func printDiagnostics(cliCtx *cli.Context) error { - return PrintDiagnostics(cliCtx, log.Root()) -} - -func PrintDiagnostics(cliCtx *cli.Context, logger log.Logger) error { - url := "http://" + cliCtx.String(debugURLFlag.Name) + "/debug/" - PrintCurentStage(url) - if cliCtx.Bool(diagnosticsPrintDownloader.Name) { - PrintSnapshotDownload(url) - } - - return nil -} - -func PrintCurentStage(url string) { - data, err := GetSyncStats(url) - if err != nil { - log.Error("Error:", err) - return - } - - fmt.Println("-------------------Stages-------------------") - - for idx, stage := range data.SyncStages.StagesList { - if idx == int(data.SyncStages.CurrentStage) { - fmt.Println("[" + stage + "]" + " - Running") - } else if idx < int(data.SyncStages.CurrentStage) { - fmt.Println("[" + stage + "]" + " - Completed") - } else { - fmt.Println("[" + stage + "]" + " - Queued") - } - } -} - -func GetSyncStats(url string) (diagnostics.SyncStatistics, error) { - data, err := MakeHttpGetCall(url + "snapshot-sync") - if err != nil { - return diagnostics.SyncStatistics{}, err - } - - if myValue, ok := data.(diagnostics.SyncStatistics); ok { - return myValue, nil - } else { - return diagnostics.SyncStatistics{}, errors.New("conversion failed: interface is not of type sync statistics") - } -} - -func PrintSnapshotDownload(url string) { - data, err := GetSyncStats(url) - if err != nil { - log.Error("Error:", err) - return - } - - fmt.Println("-------------------Snapshot Download-------------------") - - snapDownload := data.SnapshotDownload - var remainingBytes uint64 - percent := 50 - if snapDownload.Total > snapDownload.Downloaded { - remainingBytes = snapDownload.Total - snapDownload.Downloaded - percent = int((snapDownload.Downloaded*100)/snapDownload.Total) / 2 - } - - logstr := "[" - - for i := 1; i < 50; i++ { - if i < percent { - logstr += "#" - } else { - logstr += "." - } - } - - logstr += "]" - - fmt.Println("Download:", logstr, common.ByteCount(snapDownload.Downloaded), "/", common.ByteCount(snapDownload.Total)) - downloadTimeLeft := calculateTime(remainingBytes, snapDownload.DownloadRate) - - fmt.Println("Time left:", downloadTimeLeft) -} - -func MakeHttpGetCall(url string) (any, error) { - resp, err := http.Get(url) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - var data diagnostics.SyncStatistics - err = json.Unmarshal(body, &data) - if err != nil { - return nil, err - } - - return data, nil -} - -func calculateTime(amountLeft, rate uint64) string { - if rate == 0 { - return "999hrs:99m" - } - timeLeftInSeconds := amountLeft / rate - - hours := timeLeftInSeconds / 3600 - minutes := (timeLeftInSeconds / 60) % 60 - - return fmt.Sprintf("%dhrs:%dm", hours, minutes) -} diff --git a/turbo/app/make_app.go b/turbo/app/make_app.go index 7b946bc5bb3..a3e7af1a614 100644 --- a/turbo/app/make_app.go +++ b/turbo/app/make_app.go @@ -65,7 +65,6 @@ func MakeApp(name string, action cli.ActionFunc, cliFlags []cli.Flag) *cli.App { &importCommand, &snapshotCommand, &supportCommand, - &diagnosticsCommand, //&backupCommand, } return app From f65a8ae026ecb45c0de7bb70271f65f5f0176caa Mon Sep 17 00:00:00 2001 From: Mark Holt Date: Mon, 22 Apr 2024 11:51:03 +0100 Subject: [PATCH 13/14] update app usage --- cmd/diag/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/diag/main.go b/cmd/diag/main.go index 527e7251613..48f7e5f6dc1 100644 --- a/cmd/diag/main.go +++ b/cmd/diag/main.go @@ -35,7 +35,8 @@ func main() { app.Flags = []cli.Flag{} - app.HelpName = `erigon diagnostics` + app.HelpName = `Erigon Diagnostics` + app.Usage = "Display diagnostic output for a running erigon node" app.UsageText = `diag [command] [flags]` app.Action = func(context *cli.Context) error { From ec2b0b9cd3e3e2918934d381eec8eb10552b6779 Mon Sep 17 00:00:00 2001 From: dvovk Date: Mon, 22 Apr 2024 14:12:30 +0100 Subject: [PATCH 14/14] removed unused code --- cmd/diag/util/util.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cmd/diag/util/util.go b/cmd/diag/util/util.go index a2ec9008221..f6c9e6184e2 100644 --- a/cmd/diag/util/util.go +++ b/cmd/diag/util/util.go @@ -7,8 +7,6 @@ import ( "io" "net/http" "time" - - "github.com/ledgerwatch/erigon-lib/diagnostics" ) func MakeHttpGetCall(ctx context.Context, url string, data interface{}) error { @@ -32,12 +30,6 @@ func MakeHttpGetCall(ctx context.Context, url string, data interface{}) error { return err } - var dataaaa diagnostics.SyncStatistics - numerr := json.Unmarshal(body, &dataaaa) - if numerr != nil { - return numerr - } - err = json.Unmarshal(body, &data) if err != nil { return err