github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/cmd/puppeth/wizard_netstats.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:33</date> 10 //</624450070065975296> 11 12 13 package main 14 15 import ( 16 "encoding/json" 17 "os" 18 "sort" 19 "strings" 20 "sync" 21 22 "github.com/ethereum/go-ethereum/core" 23 "github.com/ethereum/go-ethereum/log" 24 "github.com/olekukonko/tablewriter" 25 ) 26 27 // 28 //配置集,用于向用户提供有关如何执行各种任务的提示。 29 func (w *wizard) networkStats() { 30 if len(w.servers) == 0 { 31 log.Info("No remote machines to gather stats from") 32 return 33 } 34 //清除一些以前的配置以从当前扫描中重新填充 35 w.conf.ethstats = "" 36 w.conf.bootnodes = w.conf.bootnodes[:0] 37 38 //遍历所有指定主机并检查其状态 39 var pend sync.WaitGroup 40 41 stats := make(serverStats) 42 for server, pubkey := range w.conf.Servers { 43 pend.Add(1) 44 45 //同时收集每个服务器的服务状态 46 go func(server string, pubkey []byte) { 47 defer pend.Done() 48 49 stat := w.gatherStats(server, pubkey, w.servers[server]) 50 51 //所有状态检查完成,报告并检查下一个服务器 52 w.lock.Lock() 53 defer w.lock.Unlock() 54 55 delete(w.services, server) 56 for service := range stat.services { 57 w.services[server] = append(w.services[server], service) 58 } 59 stats[server] = stat 60 }(server, pubkey) 61 } 62 pend.Wait() 63 64 //打印所有收集的统计数据并返回 65 stats.render() 66 } 67 68 //GatherStats收集特定远程服务器的服务统计信息。 69 func (w *wizard) gatherStats(server string, pubkey []byte, client *sshClient) *serverStat { 70 //收集一些全局统计信息以提供给向导 71 var ( 72 genesis string 73 ethstats string 74 bootnodes []string 75 ) 76 //确保到远程服务器的ssh连接有效 77 logger := log.New("server", server) 78 logger.Info("Starting remote server health-check") 79 80 stat := &serverStat{ 81 services: make(map[string]map[string]string), 82 } 83 if client == nil { 84 conn, err := dial(server, pubkey) 85 if err != nil { 86 logger.Error("Failed to establish remote connection", "err", err) 87 stat.failure = err.Error() 88 return stat 89 } 90 client = conn 91 } 92 stat.address = client.address 93 94 //客户端以某种方式连接,运行运行运行状况检查 95 logger.Debug("Checking for nginx availability") 96 if infos, err := checkNginx(client, w.network); err != nil { 97 if err != ErrServiceUnknown { 98 stat.services["nginx"] = map[string]string{"offline": err.Error()} 99 } 100 } else { 101 stat.services["nginx"] = infos.Report() 102 } 103 logger.Debug("Checking for ethstats availability") 104 if infos, err := checkEthstats(client, w.network); err != nil { 105 if err != ErrServiceUnknown { 106 stat.services["ethstats"] = map[string]string{"offline": err.Error()} 107 } 108 } else { 109 stat.services["ethstats"] = infos.Report() 110 ethstats = infos.config 111 } 112 logger.Debug("Checking for bootnode availability") 113 if infos, err := checkNode(client, w.network, true); err != nil { 114 if err != ErrServiceUnknown { 115 stat.services["bootnode"] = map[string]string{"offline": err.Error()} 116 } 117 } else { 118 stat.services["bootnode"] = infos.Report() 119 120 genesis = string(infos.genesis) 121 bootnodes = append(bootnodes, infos.enode) 122 } 123 logger.Debug("Checking for sealnode availability") 124 if infos, err := checkNode(client, w.network, false); err != nil { 125 if err != ErrServiceUnknown { 126 stat.services["sealnode"] = map[string]string{"offline": err.Error()} 127 } 128 } else { 129 stat.services["sealnode"] = infos.Report() 130 genesis = string(infos.genesis) 131 } 132 logger.Debug("Checking for explorer availability") 133 if infos, err := checkExplorer(client, w.network); err != nil { 134 if err != ErrServiceUnknown { 135 stat.services["explorer"] = map[string]string{"offline": err.Error()} 136 } 137 } else { 138 stat.services["explorer"] = infos.Report() 139 } 140 logger.Debug("Checking for wallet availability") 141 if infos, err := checkWallet(client, w.network); err != nil { 142 if err != ErrServiceUnknown { 143 stat.services["wallet"] = map[string]string{"offline": err.Error()} 144 } 145 } else { 146 stat.services["wallet"] = infos.Report() 147 } 148 logger.Debug("Checking for faucet availability") 149 if infos, err := checkFaucet(client, w.network); err != nil { 150 if err != ErrServiceUnknown { 151 stat.services["faucet"] = map[string]string{"offline": err.Error()} 152 } 153 } else { 154 stat.services["faucet"] = infos.Report() 155 } 156 logger.Debug("Checking for dashboard availability") 157 if infos, err := checkDashboard(client, w.network); err != nil { 158 if err != ErrServiceUnknown { 159 stat.services["dashboard"] = map[string]string{"offline": err.Error()} 160 } 161 } else { 162 stat.services["dashboard"] = infos.Report() 163 } 164 // 165 w.lock.Lock() 166 defer w.lock.Unlock() 167 168 if genesis != "" && w.conf.Genesis == nil { 169 g := new(core.Genesis) 170 if err := json.Unmarshal([]byte(genesis), g); err != nil { 171 log.Error("Failed to parse remote genesis", "err", err) 172 } else { 173 w.conf.Genesis = g 174 } 175 } 176 if ethstats != "" { 177 w.conf.ethstats = ethstats 178 } 179 w.conf.bootnodes = append(w.conf.bootnodes, bootnodes...) 180 181 return stat 182 } 183 184 //serverstat是服务配置参数和运行状况的集合 185 //检查要打印给用户的报告。 186 type serverStat struct { 187 address string 188 failure string 189 services map[string]map[string]string 190 } 191 192 //ServerStats是多个主机的服务器状态集合。 193 type serverStats map[string]*serverStat 194 195 // 196 //并打印到标准输出。 197 func (stats serverStats) render() { 198 //开始收集服务统计信息和配置参数 199 table := tablewriter.NewWriter(os.Stdout) 200 201 table.SetHeader([]string{"Server", "Address", "Service", "Config", "Value"}) 202 table.SetAlignment(tablewriter.ALIGN_LEFT) 203 table.SetColWidth(40) 204 205 //查找黑客分隔符的所有列的最长行 206 separator := make([]string, 5) 207 for server, stat := range stats { 208 if len(server) > len(separator[0]) { 209 separator[0] = strings.Repeat("-", len(server)) 210 } 211 if len(stat.address) > len(separator[1]) { 212 separator[1] = strings.Repeat("-", len(stat.address)) 213 } 214 if len(stat.failure) > len(separator[1]) { 215 separator[1] = strings.Repeat("-", len(stat.failure)) 216 } 217 for service, configs := range stat.services { 218 if len(service) > len(separator[2]) { 219 separator[2] = strings.Repeat("-", len(service)) 220 } 221 for config, value := range configs { 222 if len(config) > len(separator[3]) { 223 separator[3] = strings.Repeat("-", len(config)) 224 } 225 for _, val := range strings.Split(value, "\n") { 226 if len(val) > len(separator[4]) { 227 separator[4] = strings.Repeat("-", len(val)) 228 } 229 } 230 } 231 } 232 } 233 //按字母顺序填写服务器报告 234 servers := make([]string, 0, len(stats)) 235 for server := range stats { 236 servers = append(servers, server) 237 } 238 sort.Strings(servers) 239 240 for i, server := range servers { 241 //在所有服务器之间添加分隔符 242 if i > 0 { 243 table.Append(separator) 244 } 245 //按字母顺序填写服务报告 246 services := make([]string, 0, len(stats[server].services)) 247 for service := range stats[server].services { 248 services = append(services, service) 249 } 250 sort.Strings(services) 251 252 if len(services) == 0 { 253 if stats[server].failure != "" { 254 table.Append([]string{server, stats[server].failure, "", "", ""}) 255 } else { 256 table.Append([]string{server, stats[server].address, "", "", ""}) 257 } 258 } 259 for j, service := range services { 260 //在所有服务之间添加空行 261 if j > 0 { 262 table.Append([]string{"", "", "", separator[3], separator[4]}) 263 } 264 //按字母顺序填写配置报告 265 configs := make([]string, 0, len(stats[server].services[service])) 266 for service := range stats[server].services[service] { 267 configs = append(configs, service) 268 } 269 sort.Strings(configs) 270 271 for k, config := range configs { 272 for l, value := range strings.Split(stats[server].services[service][config], "\n") { 273 switch { 274 case j == 0 && k == 0 && l == 0: 275 table.Append([]string{server, stats[server].address, service, config, value}) 276 case k == 0 && l == 0: 277 table.Append([]string{"", "", service, config, value}) 278 case l == 0: 279 table.Append([]string{"", "", "", config, value}) 280 default: 281 table.Append([]string{"", "", "", "", value}) 282 } 283 } 284 } 285 } 286 } 287 table.Render() 288 } 289