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  }