github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/puppeth/wizard_netstats.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊的一部分。 11 // 12 //Go以太坊是免费软件:您可以重新发布和/或修改它 13 //根据GNU通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊的分布希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU通用公共许可证了解更多详细信息。 21 // 22 //你应该已经收到一份GNU通用公共许可证的副本 23 //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package main 26 27 import ( 28 "encoding/json" 29 "os" 30 "sort" 31 "strings" 32 "sync" 33 34 "github.com/ethereum/go-ethereum/core" 35 "github.com/ethereum/go-ethereum/log" 36 "github.com/olekukonko/tablewriter" 37 ) 38 39 // 40 //配置集,用于向用户提供有关如何执行各种任务的提示。 41 func (w *wizard) networkStats() { 42 if len(w.servers) == 0 { 43 log.Info("No remote machines to gather stats from") 44 return 45 } 46 // 47 w.conf.ethstats = "" 48 w.conf.bootnodes = w.conf.bootnodes[:0] 49 50 //遍历所有指定主机并检查其状态 51 var pend sync.WaitGroup 52 53 stats := make(serverStats) 54 for server, pubkey := range w.conf.Servers { 55 pend.Add(1) 56 57 //同时收集每个服务器的服务状态 58 go func(server string, pubkey []byte) { 59 defer pend.Done() 60 61 stat := w.gatherStats(server, pubkey, w.servers[server]) 62 63 //所有状态检查完成,报告并检查下一个服务器 64 w.lock.Lock() 65 defer w.lock.Unlock() 66 67 delete(w.services, server) 68 for service := range stat.services { 69 w.services[server] = append(w.services[server], service) 70 } 71 stats[server] = stat 72 }(server, pubkey) 73 } 74 pend.Wait() 75 76 //打印所有收集的统计数据并返回 77 stats.render() 78 } 79 80 //GatherStats收集特定远程服务器的服务统计信息。 81 func (w *wizard) gatherStats(server string, pubkey []byte, client *sshClient) *serverStat { 82 //收集一些全局统计信息以提供给向导 83 var ( 84 genesis string 85 ethstats string 86 bootnodes []string 87 ) 88 //确保到远程服务器的ssh连接有效 89 logger := log.New("server", server) 90 logger.Info("Starting remote server health-check") 91 92 stat := &serverStat{ 93 services: make(map[string]map[string]string), 94 } 95 if client == nil { 96 conn, err := dial(server, pubkey) 97 if err != nil { 98 logger.Error("Failed to establish remote connection", "err", err) 99 stat.failure = err.Error() 100 return stat 101 } 102 client = conn 103 } 104 stat.address = client.address 105 106 //客户端以某种方式连接,运行运行运行状况检查 107 logger.Debug("Checking for nginx availability") 108 if infos, err := checkNginx(client, w.network); err != nil { 109 if err != ErrServiceUnknown { 110 stat.services["nginx"] = map[string]string{"offline": err.Error()} 111 } 112 } else { 113 stat.services["nginx"] = infos.Report() 114 } 115 logger.Debug("Checking for ethstats availability") 116 if infos, err := checkEthstats(client, w.network); err != nil { 117 if err != ErrServiceUnknown { 118 stat.services["ethstats"] = map[string]string{"offline": err.Error()} 119 } 120 } else { 121 stat.services["ethstats"] = infos.Report() 122 ethstats = infos.config 123 } 124 logger.Debug("Checking for bootnode availability") 125 if infos, err := checkNode(client, w.network, true); err != nil { 126 if err != ErrServiceUnknown { 127 stat.services["bootnode"] = map[string]string{"offline": err.Error()} 128 } 129 } else { 130 stat.services["bootnode"] = infos.Report() 131 132 genesis = string(infos.genesis) 133 bootnodes = append(bootnodes, infos.enode) 134 } 135 logger.Debug("Checking for sealnode availability") 136 if infos, err := checkNode(client, w.network, false); err != nil { 137 if err != ErrServiceUnknown { 138 stat.services["sealnode"] = map[string]string{"offline": err.Error()} 139 } 140 } else { 141 stat.services["sealnode"] = infos.Report() 142 genesis = string(infos.genesis) 143 } 144 logger.Debug("Checking for explorer availability") 145 if infos, err := checkExplorer(client, w.network); err != nil { 146 if err != ErrServiceUnknown { 147 stat.services["explorer"] = map[string]string{"offline": err.Error()} 148 } 149 } else { 150 stat.services["explorer"] = infos.Report() 151 } 152 logger.Debug("Checking for wallet availability") 153 if infos, err := checkWallet(client, w.network); err != nil { 154 if err != ErrServiceUnknown { 155 stat.services["wallet"] = map[string]string{"offline": err.Error()} 156 } 157 } else { 158 stat.services["wallet"] = infos.Report() 159 } 160 logger.Debug("Checking for faucet availability") 161 if infos, err := checkFaucet(client, w.network); err != nil { 162 if err != ErrServiceUnknown { 163 stat.services["faucet"] = map[string]string{"offline": err.Error()} 164 } 165 } else { 166 stat.services["faucet"] = infos.Report() 167 } 168 logger.Debug("Checking for dashboard availability") 169 if infos, err := checkDashboard(client, w.network); err != nil { 170 if err != ErrServiceUnknown { 171 stat.services["dashboard"] = map[string]string{"offline": err.Error()} 172 } 173 } else { 174 stat.services["dashboard"] = infos.Report() 175 } 176 // 177 w.lock.Lock() 178 defer w.lock.Unlock() 179 180 if genesis != "" && w.conf.Genesis == nil { 181 g := new(core.Genesis) 182 if err := json.Unmarshal([]byte(genesis), g); err != nil { 183 log.Error("Failed to parse remote genesis", "err", err) 184 } else { 185 w.conf.Genesis = g 186 } 187 } 188 if ethstats != "" { 189 w.conf.ethstats = ethstats 190 } 191 w.conf.bootnodes = append(w.conf.bootnodes, bootnodes...) 192 193 return stat 194 } 195 196 //serverstat是服务配置参数和运行状况的集合 197 //检查要打印给用户的报告。 198 type serverStat struct { 199 address string 200 failure string 201 services map[string]map[string]string 202 } 203 204 //ServerStats是多个主机的服务器状态集合。 205 type serverStats map[string]*serverStat 206 207 // 208 // 209 func (stats serverStats) render() { 210 // 211 table := tablewriter.NewWriter(os.Stdout) 212 213 table.SetHeader([]string{"Server", "Address", "Service", "Config", "Value"}) 214 table.SetAlignment(tablewriter.ALIGN_LEFT) 215 table.SetColWidth(40) 216 217 // 218 separator := make([]string, 5) 219 for server, stat := range stats { 220 if len(server) > len(separator[0]) { 221 separator[0] = strings.Repeat("-", len(server)) 222 } 223 if len(stat.address) > len(separator[1]) { 224 separator[1] = strings.Repeat("-", len(stat.address)) 225 } 226 if len(stat.failure) > len(separator[1]) { 227 separator[1] = strings.Repeat("-", len(stat.failure)) 228 } 229 for service, configs := range stat.services { 230 if len(service) > len(separator[2]) { 231 separator[2] = strings.Repeat("-", len(service)) 232 } 233 for config, value := range configs { 234 if len(config) > len(separator[3]) { 235 separator[3] = strings.Repeat("-", len(config)) 236 } 237 for _, val := range strings.Split(value, "\n") { 238 if len(val) > len(separator[4]) { 239 separator[4] = strings.Repeat("-", len(val)) 240 } 241 } 242 } 243 } 244 } 245 // 246 servers := make([]string, 0, len(stats)) 247 for server := range stats { 248 servers = append(servers, server) 249 } 250 sort.Strings(servers) 251 252 for i, server := range servers { 253 // 254 if i > 0 { 255 table.Append(separator) 256 } 257 // 258 services := make([]string, 0, len(stats[server].services)) 259 for service := range stats[server].services { 260 services = append(services, service) 261 } 262 sort.Strings(services) 263 264 if len(services) == 0 { 265 if stats[server].failure != "" { 266 table.Append([]string{server, stats[server].failure, "", "", ""}) 267 } else { 268 table.Append([]string{server, stats[server].address, "", "", ""}) 269 } 270 } 271 for j, service := range services { 272 // 273 if j > 0 { 274 table.Append([]string{"", "", "", separator[3], separator[4]}) 275 } 276 // 277 configs := make([]string, 0, len(stats[server].services[service])) 278 for service := range stats[server].services[service] { 279 configs = append(configs, service) 280 } 281 sort.Strings(configs) 282 283 for k, config := range configs { 284 for l, value := range strings.Split(stats[server].services[service][config], "\n") { 285 switch { 286 case j == 0 && k == 0 && l == 0: 287 table.Append([]string{server, stats[server].address, service, config, value}) 288 case k == 0 && l == 0: 289 table.Append([]string{"", "", service, config, value}) 290 case l == 0: 291 table.Append([]string{"", "", "", config, value}) 292 default: 293 table.Append([]string{"", "", "", "", value}) 294 } 295 } 296 } 297 } 298 } 299 table.Render() 300 }