diff options
author | Péter Szilágyi <peterke@gmail.com> | 2017-10-19 18:59:02 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2017-11-21 21:09:28 +0800 |
commit | 8c78449a9ef8f2a77cc1ff94f9a0a3178af21408 (patch) | |
tree | 61902b11284d1455ca7c109a512b93048d53ad4f /cmd/puppeth/wizard_netstats.go | |
parent | 005665867d50a4b38e269b6b84156db2f75469a3 (diff) | |
download | go-tangerine-8c78449a9ef8f2a77cc1ff94f9a0a3178af21408.tar go-tangerine-8c78449a9ef8f2a77cc1ff94f9a0a3178af21408.tar.gz go-tangerine-8c78449a9ef8f2a77cc1ff94f9a0a3178af21408.tar.bz2 go-tangerine-8c78449a9ef8f2a77cc1ff94f9a0a3178af21408.tar.lz go-tangerine-8c78449a9ef8f2a77cc1ff94f9a0a3178af21408.tar.xz go-tangerine-8c78449a9ef8f2a77cc1ff94f9a0a3178af21408.tar.zst go-tangerine-8c78449a9ef8f2a77cc1ff94f9a0a3178af21408.zip |
cmd/puppeth: reorganize stats reports to make it readable
Diffstat (limited to 'cmd/puppeth/wizard_netstats.go')
-rw-r--r-- | cmd/puppeth/wizard_netstats.go | 216 |
1 files changed, 112 insertions, 104 deletions
diff --git a/cmd/puppeth/wizard_netstats.go b/cmd/puppeth/wizard_netstats.go index c06972198..7d8e84242 100644 --- a/cmd/puppeth/wizard_netstats.go +++ b/cmd/puppeth/wizard_netstats.go @@ -18,8 +18,8 @@ package main import ( "encoding/json" - "fmt" "os" + "sort" "strings" "github.com/ethereum/go-ethereum/core" @@ -29,7 +29,7 @@ import ( // networkStats verifies the status of network components and generates a protip // configuration set to give users hints on how to do various tasks. -func (w *wizard) networkStats(tips bool) { +func (w *wizard) networkStats() { if len(w.servers) == 0 { log.Error("No remote machines to gather stats from") return @@ -37,51 +37,53 @@ func (w *wizard) networkStats(tips bool) { protips := new(protips) // Iterate over all the specified hosts and check their status - stats := tablewriter.NewWriter(os.Stdout) - stats.SetHeader([]string{"Server", "IP", "Status", "Service", "Details"}) - stats.SetColWidth(100) + stats := make(serverStats) for server, pubkey := range w.conf.Servers { client := w.servers[server] logger := log.New("server", server) logger.Info("Starting remote server health-check") - // If the server is not connected, try to connect again + stat := &serverStat{ + address: client.address, + services: make(map[string]map[string]string), + } + stats[client.server] = stat + if client == nil { conn, err := dial(server, pubkey) if err != nil { logger.Error("Failed to establish remote connection", "err", err) - stats.Append([]string{server, "", err.Error(), "", ""}) + stat.failure = err.Error() continue } client = conn } // Client connected one way or another, run health-checks - services := make(map[string]string) logger.Debug("Checking for nginx availability") if infos, err := checkNginx(client, w.network); err != nil { if err != ErrServiceUnknown { - services["nginx"] = err.Error() + stat.services["nginx"] = map[string]string{"offline": err.Error()} } } else { - services["nginx"] = infos.String() + stat.services["nginx"] = infos.Report() } logger.Debug("Checking for ethstats availability") if infos, err := checkEthstats(client, w.network); err != nil { if err != ErrServiceUnknown { - services["ethstats"] = err.Error() + stat.services["ethstats"] = map[string]string{"offline": err.Error()} } } else { - services["ethstats"] = infos.String() + stat.services["ethstats"] = infos.Report() protips.ethstats = infos.config } logger.Debug("Checking for bootnode availability") if infos, err := checkNode(client, w.network, true); err != nil { if err != ErrServiceUnknown { - services["bootnode"] = err.Error() + stat.services["bootnode"] = map[string]string{"offline": err.Error()} } } else { - services["bootnode"] = infos.String() + stat.services["bootnode"] = infos.Report() protips.genesis = string(infos.genesis) protips.bootFull = append(protips.bootFull, infos.enodeFull) @@ -92,41 +94,33 @@ func (w *wizard) networkStats(tips bool) { logger.Debug("Checking for sealnode availability") if infos, err := checkNode(client, w.network, false); err != nil { if err != ErrServiceUnknown { - services["sealnode"] = err.Error() + stat.services["sealnode"] = map[string]string{"offline": err.Error()} } } else { - services["sealnode"] = infos.String() + stat.services["sealnode"] = infos.Report() protips.genesis = string(infos.genesis) } logger.Debug("Checking for faucet availability") if infos, err := checkFaucet(client, w.network); err != nil { if err != ErrServiceUnknown { - services["faucet"] = err.Error() + stat.services["faucet"] = map[string]string{"offline": err.Error()} } } else { - services["faucet"] = infos.String() + stat.services["faucet"] = infos.Report() } logger.Debug("Checking for dashboard availability") if infos, err := checkDashboard(client, w.network); err != nil { if err != ErrServiceUnknown { - services["dashboard"] = err.Error() + stat.services["dashboard"] = map[string]string{"offline": err.Error()} } } else { - services["dashboard"] = infos.String() + stat.services["dashboard"] = infos.Report() } // All status checks complete, report and check next server delete(w.services, server) - for service := range services { + for service := range stat.services { w.services[server] = append(w.services[server], service) } - server, address := client.server, client.address - for service, status := range services { - stats.Append([]string{server, address, "online", service, status}) - server, address = "", "" - } - if len(services) == 0 { - stats.Append([]string{server, address, "online", "", ""}) - } } // If a genesis block was found, load it into our configs if protips.genesis != "" && w.conf.genesis == nil { @@ -145,91 +139,105 @@ func (w *wizard) networkStats(tips bool) { w.conf.bootLight = protips.bootLight // Print any collected stats and return - if !tips { - stats.Render() - } else { - protips.print(w.network) - } + stats.render() } -// protips contains a collection of network infos to report pro-tips -// based on. -type protips struct { - genesis string - network int64 - bootFull []string - bootLight []string - ethstats string +// serverStat is a collection of service configuration parameters and health +// check reports to print to the user. +type serverStat struct { + address string + failure string + services map[string]map[string]string } -// print analyzes the network information available and prints a collection of -// pro tips for the user's consideration. -func (p *protips) print(network string) { - // If a known genesis block is available, display it and prepend an init command - fullinit, lightinit := "", "" - if p.genesis != "" { - fullinit = fmt.Sprintf("geth --datadir=$HOME/.%s init %s.json && ", network, network) - lightinit = fmt.Sprintf("geth --datadir=$HOME/.%s --light init %s.json && ", network, network) - } - // If an ethstats server is available, add the ethstats flag - statsflag := "" - if p.ethstats != "" { - if strings.Contains(p.ethstats, " ") { - statsflag = fmt.Sprintf(` --ethstats="yournode:%s"`, p.ethstats) - } else { - statsflag = fmt.Sprintf(` --ethstats=yournode:%s`, p.ethstats) - } - } - // If bootnodes have been specified, add the bootnode flag - bootflagFull := "" - if len(p.bootFull) > 0 { - bootflagFull = fmt.Sprintf(` --bootnodes %s`, strings.Join(p.bootFull, ",")) - } - bootflagLight := "" - if len(p.bootLight) > 0 { - bootflagLight = fmt.Sprintf(` --bootnodes %s`, strings.Join(p.bootLight, ",")) - } - // Assemble all the known pro-tips - var tasks, tips []string - - tasks = append(tasks, "Run an archive node with historical data") - tips = append(tips, fmt.Sprintf("%sgeth --networkid=%d --datadir=$HOME/.%s --cache=1024%s%s", fullinit, p.network, network, statsflag, bootflagFull)) +// serverStats is a collection of server stats for multiple hosts. +type serverStats map[string]*serverStat - tasks = append(tasks, "Run a full node with recent data only") - tips = append(tips, fmt.Sprintf("%sgeth --networkid=%d --datadir=$HOME/.%s --cache=512 --fast%s%s", fullinit, p.network, network, statsflag, bootflagFull)) +// render converts the gathered statistics into a user friendly tabular report +// and prints it to the standard output. +func (stats serverStats) render() { + // Start gathering service statistics and config parameters + table := tablewriter.NewWriter(os.Stdout) - tasks = append(tasks, "Run a light node with on demand retrievals") - tips = append(tips, fmt.Sprintf("%sgeth --networkid=%d --datadir=$HOME/.%s --light%s%s", lightinit, p.network, network, statsflag, bootflagLight)) + table.SetHeader([]string{"Server", "Address", "Service", "Config", "Value"}) + table.SetAlignment(tablewriter.ALIGN_LEFT) + table.SetColWidth(100) - tasks = append(tasks, "Run an embedded node with constrained memory") - tips = append(tips, fmt.Sprintf("%sgeth --networkid=%d --datadir=$HOME/.%s --cache=32 --light%s%s", lightinit, p.network, network, statsflag, bootflagLight)) - - // If the tips are short, display in a table - short := true - for _, tip := range tips { - if len(tip) > 100 { - short = false - break + // Find the longest lines for all columns for the hacked separator + separator := make([]string, 5) + for server, stat := range stats { + if len(server) > len(separator[0]) { + separator[0] = strings.Repeat("-", len(server)) + } + if len(stat.address) > len(separator[1]) { + separator[1] = strings.Repeat("-", len(stat.address)) + } + for service, configs := range stat.services { + if len(service) > len(separator[2]) { + separator[2] = strings.Repeat("-", len(service)) + } + for config, value := range configs { + if len(config) > len(separator[3]) { + separator[3] = strings.Repeat("-", len(config)) + } + if len(value) > len(separator[4]) { + separator[4] = strings.Repeat("-", len(value)) + } + } } } - fmt.Println() - if short { - howto := tablewriter.NewWriter(os.Stdout) - howto.SetHeader([]string{"Fun tasks for you", "Tips on how to"}) - howto.SetColWidth(100) + // Fill up the server report in alphabetical order + servers := make([]string, 0, len(stats)) + for server := range stats { + servers = append(servers, server) + } + sort.Strings(servers) - for i := 0; i < len(tasks); i++ { - howto.Append([]string{tasks[i], tips[i]}) + for i, server := range servers { + // Add a separator between all servers + if i > 0 { + table.Append(separator) + } + // Fill up the service report in alphabetical order + services := make([]string, 0, len(stats[server].services)) + for service := range stats[server].services { + services = append(services, service) + } + sort.Strings(services) + + for j, service := range services { + // Add an empty line between all services + if j > 0 { + table.Append([]string{"", "", "", separator[3], separator[4]}) + } + // Fill up the config report in alphabetical order + configs := make([]string, 0, len(stats[server].services[service])) + for service := range stats[server].services[service] { + configs = append(configs, service) + } + sort.Strings(configs) + + for k, config := range configs { + switch { + case j == 0 && k == 0: + table.Append([]string{server, stats[server].address, service, config, stats[server].services[service][config]}) + case k == 0: + table.Append([]string{"", "", service, config, stats[server].services[service][config]}) + default: + table.Append([]string{"", "", "", config, stats[server].services[service][config]}) + } + } } - howto.Render() - return - } - // Meh, tips got ugly, split into many lines - for i := 0; i < len(tasks); i++ { - fmt.Println(tasks[i]) - fmt.Println(strings.Repeat("-", len(tasks[i]))) - fmt.Println(tips[i]) - fmt.Println() - fmt.Println() } + table.Render() +} + +// protips contains a collection of network infos to report pro-tips +// based on. +type protips struct { + genesis string + network int64 + bootFull []string + bootLight []string + ethstats string } |