github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/cmd/geth/log_display_dash.go (about)

     1  // ---
     2  //┌Import | local_head ◼ n=5047652 ⬡=0x33f6878a… txs=1 time=21s ago──────────────────────────────────┐
     3  //│                                                                                                  │
     4  //└──────────────────────────────────────────────────────────────────────────────────────────────────┘
     5  //┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
     6  //│n=5047652] ∆ blks=1 (inserted_at=2017-12-19 09:51:35 -0600 CST took=23ms)                         │
     7  //│                                                                                                  │
     8  //│                                                                                                  │
     9  //│                                                                                                  │
    10  //│n=5047652] ∑ mgas= 0/   1blks                                                                     │
    11  //│                                                                                                  │
    12  //│                                                                                                  │
    13  //│                                                                                                  │
    14  //│n=5047652] ∑ txs=  1/   1blks                                                                     │
    15  //│                                ▃          ▆            ▅                               ▇         │
    16  //│    ▃ ▁    ▁    ▂  ▄                      ▆  ▁▂ ▄   ▃       ▅    ▁    ▁          ▇▆      ▂        │
    17  //│▁▇   ▃  ▆   ▁▁▁   ▁ ▂ ▂▁▂▂▆▂▁▁▁  ▁▄▁ ▃▁▂▅▇     ▅ ▄ ▁      ▂    ▆   ▂▄▇ ▁ ▁ ▃▅▄▇▃   ▃  ▃   ▂ ▁   ▁▁│
    18  //│                                                                                                  │
    19  //└──────────────────────────────────────────────────────────────────────────────────────────────────┘
    20  //┌Peers (13 / 25)───────────────────────────────────────────────────────────────────────────────────┐
    21  //│                                                                                                  │
    22  //│                                                                                                  │
    23  //│                                                                                                  │
    24  //│                                                                                                  │
    25  //│                                                                                                  │
    26  //│                                                                                                  │
    27  //
    28  //│Peer id=5701cea16e32cb06 eth/63 [Parity/v1.7.9-stable-12940e4-20171113/x86_64-linux-gnu/rustc1.21…│
    29  //│Peer id=8310b1f98b9b7afe eth/63 [Parity/v1.7.0-unstable-5f2cabd-20170727/x86_64-linux-gnu/rustc1.…│
    30  //│Peer id=5fbfb426fbb46f8b eth/63 [Parity/v1.7.7-stable-eb7c648-20171015/x86_64-linux-gnu/rustc1.20…│
    31  //│Peer id=1922bfd2acc1e82f eth/63 [Parity/v1.8.2-beta-1b6588c-20171025/x86_64-linux-gnu/rustc1.21.0…│
    32  //│Peer id=8ed199326f981ae9 eth/63 [Parity/v1.8.0-beta-9882902-20171015/x86_64-linux-gnu/rustc1.20.0…│
    33  //│Peer id=c89d548e2a55d324 eth/63 [Parity/v1.8.2-beta-1b6588c-20171025/x86_64-linux-gnu/rustc1.21.0…│
    34  //│Peer id=13c960f1da9a6337 eth/63 [Parity/v1.8.4-beta-c74c8c1-20171211/x86_64-linux-gnu/rustc1.22.1…│
    35  //│Peer id=021eb56de4a7b725 eth/63 [Parity/v1.6.9-stable-d44b008-20170716/x86_64-linux-gnu/rustc1.18…│
    36  //│Peer id=385ffdfb7f7cd2f5 eth/63 [Geth/v4.0.0/windows/go1.8] [hs 0.00/s, bs 0.00/s, rs 0.00/s, ss …│
    37  //│Peer id=d5a5d20cb8b77e14 eth/63 [Parity/v1.8.2-beta-1b6588c-20171025/x86_64-linux-gnu/rustc1.21.0…│
    38  //│Peer id=5f259d71e80f710b eth/63 [Parity/v1.7.9-stable-12940e4-20171113/x86_64-linux-gnu/rustc1.21…│
    39  //│Peer id=e7f3c98896581fee eth/63 [Parity/v1.7.9-unstable-12940e4-20171113/x86_64-linux-gnu/rustc1.…│
    40  //│Peer id=cb0e1d693f950573 eth/63 [Parity/v1.7.10-stable-3931713-20171211/x86_64-linux-gnu/rustc1.2…│
    41  //│                                                                                                  │
    42  //│                                                                                                  │
    43  //└──────────────────────────────────────────────────────────────────────────────────────────────────┘
    44  // ---
    45  
    46  package main
    47  
    48  import (
    49  	"fmt"
    50  	"time"
    51  
    52  	"github.com/ethereumproject/go-ethereum/core"
    53  	"github.com/ethereumproject/go-ethereum/eth"
    54  	"github.com/ethereumproject/go-ethereum/logger"
    55  	"github.com/ethereumproject/go-ethereum/logger/glog"
    56  	"github.com/ethereumproject/go-ethereum/metrics"
    57  	"github.com/gizak/termui"
    58  	"gopkg.in/urfave/cli.v1"
    59  )
    60  
    61  const (
    62  	tuiHeaderHeight = 2
    63  	tuiHeaderStart  = 1
    64  	tuiSmallHeight  = 3
    65  	tuiMediumHeight = 5
    66  	tuiLargeHeight  = 8
    67  	tuiSmallWidth   = 20
    68  	tuiMediumWidth  = 50
    69  	tuiLargeWidth   = 100
    70  
    71  	tuiSpaceHeight = 1
    72  
    73  	tuiDataLimit = 100
    74  )
    75  
    76  var (
    77  	headerInfo      *termui.Par
    78  	syncheightGauge *termui.Gauge
    79  
    80  	peerCountSpark       termui.Sparkline
    81  	peerCountSparkHolder *termui.Sparklines
    82  
    83  	peerList     *termui.List
    84  	peerListData []string
    85  
    86  	mgasSpark             termui.Sparkline
    87  	txsSpark              termui.Sparkline
    88  	blkSpark              termui.Sparkline
    89  	blkMgasTxsSparkHolder *termui.Sparklines
    90  )
    91  
    92  func tuiDrawDash(e *eth.Ethereum) {
    93  	if currentMode == lsModeImport || currentMode == lsModeDiscover {
    94  		syncheightGauge.Label = ""
    95  	}
    96  	if e != nil && e.IsListening() {
    97  		cb := e.BlockChain().GetBlockByNumber(currentBlockNumber)
    98  		cid := e.ChainConfig().GetChainID()
    99  		cnet := e.NetVersion()
   100  		cname := ""
   101  		if id := core.GetCacheChainIdentity(); id != "" {
   102  			cname = id
   103  		}
   104  		headerInfo.Text = fmt.Sprintf(" Mode=%s Chain=%v(%d) Chain Id=%d \n"+
   105  			" local_head ◼ n=%d ⬡=%s txs=%d time=%v ago",
   106  			currentMode, cname, cnet, cid, currentBlockNumber, cb.Hash().Hex()[:10]+"…", cb.Transactions().Len(),
   107  			time.Since(time.Unix(cb.Time().Int64(), 0)).Round(time.Second))
   108  		syncheightGauge.BorderLabel = fmt.Sprintf("Sync")
   109  
   110  	}
   111  	termui.Render(headerInfo, syncheightGauge, peerCountSparkHolder, peerList, blkMgasTxsSparkHolder)
   112  }
   113  
   114  func tuiSetupDashComponents() {
   115  
   116  	/// Config Info Header
   117  	headerInfo = termui.NewPar("")
   118  	headerInfo.Height = tuiHeaderHeight
   119  	headerInfo.Border = false
   120  	headerInfo.X = tuiHeaderStart
   121  	headerInfo.TextBgColor = termui.ColorWhite
   122  	headerInfo.TextFgColor = termui.ColorBlack
   123  	headerInfo.SetWidth(termui.TermWidth() - 1)
   124  	//// Sync height gauge
   125  	syncheightGauge = termui.NewGauge()
   126  	syncheightGauge.Percent = 0
   127  	syncheightGauge.BarColor = termui.ColorRed
   128  	syncheightGauge.Height = tuiSmallHeight
   129  	syncheightGauge.Width = tuiLargeWidth
   130  	syncheightGauge.Y = tuiHeaderHeight + 1
   131  	//// Mgas spark
   132  	mgasSpark = termui.Sparkline{}
   133  	mgasSpark.Title = "Mgas"
   134  	mgasSpark.Data = []int{}
   135  	mgasSpark.Height = tuiSmallHeight
   136  	mgasSpark.LineColor = termui.ColorYellow
   137  	//// Txs spark
   138  	txsSpark = termui.Sparkline{}
   139  	txsSpark.Title = "Txs"
   140  	txsSpark.Data = []int{}
   141  	txsSpark.Height = tuiSmallHeight
   142  	txsSpark.LineColor = termui.ColorMagenta
   143  	//// Blk spark
   144  	blkSpark = termui.Sparkline{}
   145  	blkSpark.Title = "Blks"
   146  	blkSpark.Data = []int{}
   147  	blkSpark.Height = tuiSmallHeight
   148  	blkSpark.LineColor = termui.ColorGreen
   149  	//// MgasTxs spark holder
   150  	blkMgasTxsSparkHolder = termui.NewSparklines(blkSpark, mgasSpark, txsSpark)
   151  	blkMgasTxsSparkHolder.Height = mgasSpark.Height + txsSpark.Height + blkSpark.Height + tuiSpaceHeight*6
   152  	blkMgasTxsSparkHolder.Width = syncheightGauge.Width
   153  	blkMgasTxsSparkHolder.Y = syncheightGauge.Y + syncheightGauge.Height
   154  	blkMgasTxsSparkHolder.X = syncheightGauge.X
   155  
   156  	//// Peer count spark
   157  	peerCountSpark = termui.Sparkline{}
   158  	peerCountSpark.LineColor = termui.ColorBlue
   159  	peerCountSpark.Data = []int{0}
   160  	peerCountSpark.Height = tuiMediumHeight
   161  	//// Peer count spark holder
   162  	peerCountSparkHolder = termui.NewSparklines(peerCountSpark)
   163  	peerCountSparkHolder.BorderLabel = "Peers (0) | Bytes (0 rx / 0 tx) | Mean Rate (0 rx / 0 tx)"
   164  	peerCountSparkHolder.BorderLabelFg = termui.ColorBlue
   165  	peerCountSparkHolder.BorderBottom = false
   166  	peerCountSparkHolder.X = 0
   167  	peerCountSparkHolder.Y = blkMgasTxsSparkHolder.Y + blkMgasTxsSparkHolder.Height
   168  	peerCountSparkHolder.Height = tuiMediumHeight + tuiSpaceHeight*3
   169  	peerCountSparkHolder.Width = syncheightGauge.Width
   170  
   171  	//// Peer list
   172  	peerList = termui.NewList()
   173  	peerList.Items = peerListData
   174  	peerList.X = 0
   175  	peerList.Y = peerCountSparkHolder.Y + peerCountSparkHolder.Height
   176  	peerList.Width = peerCountSparkHolder.Width
   177  	peerList.Height = tuiLargeHeight * 2
   178  	peerList.BorderTop = false
   179  }
   180  
   181  func addDataWithLimit(sl []int, dataPoint int, maxLen int) []int {
   182  	if len(sl) > maxLen {
   183  		sl = append(sl[1:], dataPoint)
   184  		return sl
   185  	}
   186  	sl = append(sl, dataPoint)
   187  	return sl
   188  }
   189  
   190  // dashDisplaySystem is an experimental display system intended as a proof of concept for the display dispatch system
   191  var dashDisplaySystem = displayEventHandlers{
   192  	{
   193  		eventT: logEventBefore,
   194  		handlers: displayEventHandlerFns{
   195  			func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) {
   196  				// Disable display logging.
   197  				d := glog.GetDisplayable()
   198  				glog.SetD(0)
   199  				go func() {
   200  					// Reset display logs.
   201  					defer glog.SetD(int(*d))
   202  
   203  					err := termui.Init()
   204  					if err != nil {
   205  						panic(err)
   206  					}
   207  					tuiSetupDashComponents()
   208  					tuiSetupHandlers()
   209  					if currentBlockNumber == 0 {
   210  						_, c, _, _, _ := e.Downloader().Progress()
   211  						currentBlockNumber = c
   212  					}
   213  					tuiDrawDash(e)
   214  
   215  					termui.Loop()
   216  				}()
   217  			},
   218  		},
   219  	},
   220  	{
   221  		eventT: logEventCoreChainInsert,
   222  		ev:     core.ChainInsertEvent{},
   223  		handlers: displayEventHandlerFns{
   224  			func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) {
   225  				switch d := evData.(type) {
   226  				case core.ChainInsertEvent:
   227  					localheight := d.LastNumber
   228  					_, head, syncheight, _, _ := e.Downloader().Progress()
   229  					if head > localheight {
   230  						localheight = head
   231  					}
   232  					syncheightGauge.Percent = int(calcPercent(localheight, syncheight))
   233  
   234  					if localheight >= syncheight {
   235  						syncheightGauge.Label = fmt.Sprintf("%d", localheight)
   236  						syncheightGauge.BarColor = termui.ColorGreen
   237  					} else {
   238  						syncheightGauge.Label = fmt.Sprintf("%d / %d", localheight, syncheight)
   239  						syncheightGauge.BarColor = termui.ColorRed
   240  					}
   241  
   242  					if currentBlockNumber != 0 {
   243  						b := e.BlockChain().GetBlockByNumber(localheight)
   244  						if b == nil {
   245  							return
   246  						}
   247  						blks, txs, mgas := calcBlockDiff(e, currentBlockNumber, b)
   248  						// blk
   249  						blkMgasTxsSparkHolder.Lines[0].Data = addDataWithLimit(blkMgasTxsSparkHolder.Lines[0].Data, blks, tuiDataLimit)
   250  						blkMgasTxsSparkHolder.Lines[0].Title = fmt.Sprintf("n=%d] ∆ blks=%d (inserted_at=%v took=%v)", localheight, blks, time.Now().Round(time.Second), d.Elasped.Round(time.Millisecond))
   251  						// mgas
   252  						blkMgasTxsSparkHolder.Lines[1].Data = addDataWithLimit(blkMgasTxsSparkHolder.Lines[1].Data, mgas, tuiDataLimit)
   253  						blkMgasTxsSparkHolder.Lines[1].Title = fmt.Sprintf("n=%d] ∑ mgas=%2d/%4dblks", localheight, mgas, blks)
   254  						// txs
   255  						blkMgasTxsSparkHolder.Lines[2].Data = addDataWithLimit(blkMgasTxsSparkHolder.Lines[2].Data, txs, tuiDataLimit)
   256  						blkMgasTxsSparkHolder.Lines[2].Title = fmt.Sprintf("n=%d] ∑ txs=%3d/%4dblks", localheight, txs, blks)
   257  					}
   258  					currentBlockNumber = localheight
   259  					tuiDrawDash(e)
   260  				default:
   261  					panic(d)
   262  				}
   263  			},
   264  		},
   265  	},
   266  	{
   267  		eventT: logEventAfter,
   268  		handlers: displayEventHandlerFns{
   269  			func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) {
   270  				termui.StopLoop()
   271  				termui.Close()
   272  				return
   273  
   274  			},
   275  		},
   276  	},
   277  	{
   278  		eventT: logEventInterval,
   279  		handlers: displayEventHandlerFns{
   280  			func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) {
   281  				rxP2P := metrics.P2PInBytes
   282  				txP2P := metrics.P2POutBytes
   283  				rxBytes := rxP2P.Count()
   284  				txByes := txP2P.Count()
   285  				rxRateMean := rxP2P.RateMean()
   286  				txRateMean := txP2P.RateMean()
   287  				peers := e.Downloader().GetPeers()
   288  				peerCountSparkHolder.Lines[0].Data = addDataWithLimit(peerCountSparkHolder.Lines[0].Data, int(peers.Len()), tuiDataLimit)
   289  				peerCountSparkHolder.BorderLabel = fmt.Sprintf("Peers (%d / %d) | Bytes (%d rx / %d tx) | Mean Rate (%.2f rx / %.2f tx)",
   290  					int(peers.Len()), ctx.GlobalInt(aliasableName(MaxPeersFlag.Name, ctx)), rxBytes, txByes, rxRateMean, txRateMean)
   291  				peerListData = []string{}
   292  				for _, p := range peers.AllPeers() {
   293  					peerListData = append(peerListData, p.String())
   294  				}
   295  				peerList.Items = peerListData
   296  				tuiDrawDash(e)
   297  			},
   298  		},
   299  	},
   300  }
   301  
   302  func tuiSetupHandlers() {
   303  	termui.Handle("interrupt", func(tue termui.Event) {
   304  		glog.V(logger.Error).Errorln("interrupt 1")
   305  		termui.StopLoop()
   306  		termui.Close()
   307  	})
   308  	termui.Handle("/interrupt", func(tue termui.Event) {
   309  		glog.V(logger.Error).Errorln("interrupt 2")
   310  		termui.StopLoop()
   311  		termui.Close()
   312  	})
   313  	termui.Handle("/sys/interrupt", func(tue termui.Event) {
   314  		glog.V(logger.Error).Errorln("interrupt 3")
   315  		termui.StopLoop()
   316  		termui.Close()
   317  	})
   318  	termui.Handle("/sys/kbd/C-c", func(tue termui.Event) {
   319  		glog.V(logger.Error).Errorln("/sys/kbd/C-c")
   320  		termui.StopLoop()
   321  		termui.Close()
   322  	})
   323  	termui.Handle("/sys/kbd/C-x", func(tue termui.Event) {
   324  		glog.V(logger.Error).Errorln("/sys/kbd/C-x")
   325  		termui.StopLoop()
   326  		termui.Close()
   327  	})
   328  	termui.Handle("/sys/kbd/C-z", func(tue termui.Event) {
   329  		glog.V(logger.Error).Errorln("/sys/kbd/C-z")
   330  		termui.StopLoop()
   331  		termui.Close()
   332  	})
   333  	termui.Handle("/sys/kbd/q", func(tue termui.Event) {
   334  		glog.V(logger.Error).Errorln("/sys/kbd/q")
   335  		termui.StopLoop()
   336  		termui.Close()
   337  	})
   338  	termui.Handle("/sys/kbd/r", func(tue termui.Event) {
   339  		// Just check for len > 1 for an arbitrary set because they're all updated simultaneously.
   340  		// This is also a totally opinionated and convenience thing.
   341  		if len(blkMgasTxsSparkHolder.Lines[0].Data) > 1 {
   342  			blkMgasTxsSparkHolder.Lines[0].Data = blkMgasTxsSparkHolder.Lines[0].Data[1:]
   343  			blkMgasTxsSparkHolder.Lines[1].Data = blkMgasTxsSparkHolder.Lines[1].Data[1:]
   344  			blkMgasTxsSparkHolder.Lines[2].Data = blkMgasTxsSparkHolder.Lines[2].Data[1:]
   345  		}
   346  	})
   347  }