github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/cmd/geth/log_display_gitlike.go (about) 1 /* 2 2018-06-02 17:52:15 [INFO] | ~ Download start ⟪peer:ae6c86671cdc73b9@[Geth/v1.8.10-stable-eae63c51/linux-amd64/go1.10] eth/63⟫ hash=⟪0xc1c9a09…⟫ TD=⟪337709287732711584590⟫ 3 2018-06-02 17:52:16 [INFO] | ~ Download fail ⟪peer:ae6c86671cdc73b9@[Geth/v1.8.10-stable-eae63c51/linux-amd64/go1.10] eth/63⟫ err=⟪block fetch canceled (requested)⟫ 4 2018-06-02 17:52:25 [INFO] : Discover ➫⟪#5923278 0x93c4980…⟫ ✌︎︎︎⟪ 1/25 peers⟫ qos=⟪rtt=18s ttl=1m0s conf=1.00⟫ 5 2018-06-02 17:52:25 [INFO] | ~ Download start ⟪peer:20ec67d824529152@[Geth/v5.2.1-456053c/linux/go1.9.5] eth/63⟫ hash=⟪0x7246ca0…⟫ TD=⟪308559817009843748587⟫ 6 2018-06-02 17:52:29 [INFO] |\ 7 2018-06-02 17:52:29 [INFO] | * Insert blocks=⟪processed= 2 queued= 0 ignored= 0 txs= 32⟫ ◼=⟪n= 5923280 hash=0x6bba7fd… time=1m9.032s ago⟫ took=⟪2.885s⟫ 8 2018-06-02 17:52:29 [INFO] |/ 9 2018-06-02 17:52:29 [INFO] | ~ Download done ⟪peer:20ec67d824529152@[Geth/v5.2.1-456053c/linux/go1.9.5] eth/63⟫ hash=⟪0x7246ca0…⟫ TD=⟪308559817009843748587⟫ 10 2018-06-02 17:52:29 [INFO] '* Inserted blocks=⟪processed= 2 queued= 0 ignored= 0 txs= 10⟫ ◼=⟪n= 5923282 hash=0x7246ca0… time=1m2.094s ago⟫ took=⟪62ms⟫ 11 2018-06-02 17:52:35 [INFO] | ~ Download start ⟪peer:73683b51a0d62db7@[Geth/v1.8.0-stable-5f540757/linux-amd64/go1.9.4] eth/63⟫ hash=⟪0xca24109…⟫ TD=⟪4368733862078872596412⟫ 12 2018-06-02 17:52:55 [INFO] | ~ Download fail ⟪peer:73683b51a0d62db7@[Geth/v1.8.0-stable-5f540757/linux-amd64/go1.9.4] eth/63⟫ err=⟪block header download canceled (requested)⟫ 13 2018-06-02 17:52:55 [INFO] | ~ Download start ⟪peer:8f185d68e6f283ad@[Geth/v1.8.10-stable-eae63c51/linux-amd64/go1.10.1] eth/63⟫ hash=⟪0xfc7888d…⟫ TD=⟪4539449821322174516116⟫ 14 2018-06-02 17:52:56 [INFO] * Import ◼=⟪n= 5923283 hash=0x2bc7de5 miner=0x9eab4b0 time=1m6.7s ago⟫ peer=⟪7e2995638c8a3c7e⟫ 15 2018-06-02 17:53:01 [INFO] | ~ Download fail ⟪peer:8f185d68e6f283ad@[Geth/v1.8.10-stable-eae63c51/linux-amd64/go1.10.1] eth/63⟫ err=⟪block fetch canceled (requested)⟫ 16 2018-06-02 17:53:07 [INFO] * Import ◼=⟪n= 5923284 hash=0xb9df06b miner=0xdf7d7e0 time=12.478s ago⟫ peer=⟪20ec67d824529152⟫ 17 2018-06-02 17:53:19 [INFO] | ~ Download start ⟪peer:8b6d82f20bfdfe97@[Parity/v1.7.12-shapeshift-f96d152-20180109/x86_64-linux-gnu/rustc1.23.0] eth/63⟫ hash=⟪0xe41a94e…⟫ TD=⟪4539806318512030442218⟫ 18 2018-06-02 17:53:21 [WARN] | ~ Download fail ⟪peer:8b6d82f20bfdfe97@[Parity/v1.7.12-shapeshift-f96d152-20180109/x86_64-linux-gnu/rustc1.23.0] eth/63⟫ err=⟪empty header set by peer⟫ 19 2018-06-02 17:53:25 [INFO] | ~ Download start ⟪peer:c1853910b52ee0ed@[Geth/v1.8.7-stable-66432f38/linux-amd64/go1.10] eth/63⟫ hash=⟪0x9bdd0fc…⟫ TD=⟪4539672566919915992687⟫ 20 2018-06-02 17:53:26 [INFO] | ~ Download fail ⟪peer:c1853910b52ee0ed@[Geth/v1.8.7-stable-66432f38/linux-amd64/go1.10] eth/63⟫ err=⟪block fetch canceled (requested)⟫ 21 2018-06-02 17:53:45 [INFO] | ~ Download start ⟪peer:a13882fc0f60fd5e@[Geth/v1.7.2-stable-1db4ecdc/windows-amd64/go1.9] eth/63⟫ hash=⟪0x7de95fd…⟫ TD=⟪4539596261192099816569⟫ 22 2018-06-02 17:54:00 [INFO] | ~ Download fail ⟪peer:a13882fc0f60fd5e@[Geth/v1.7.2-stable-1db4ecdc/windows-amd64/go1.9] eth/63⟫ err=⟪block fetch canceled (requested)⟫ 23 2018-06-02 17:54:04 [INFO] * Import ◼=⟪n= 5923285 hash=0xf0255ba miner=0x9eab4b0 time=58.545s ago⟫ peer=⟪7e2995638c8a3c7e⟫ 24 2018-06-02 17:54:07 [INFO] * Import ◼=⟪n= 5923286 hash=0x89024f1 miner=0x1c0fa19 time=4.023s ago⟫ peer=⟪20ec67d824529152⟫ 25 2018-06-02 17:54:15 [INFO] | ~ Download start ⟪peer:a8300e12fbb0de00@[Geth/v1.8.6-patched-leveldb-8818ab0b/linux-amd64/go1.9.2] eth/63⟫ hash=⟪0x8264a5a…⟫ TD=⟪4539819098507839148947⟫ 26 */ 27 28 package main 29 30 import ( 31 "fmt" 32 "math/big" 33 "strings" 34 "time" 35 36 "github.com/ethereumproject/go-ethereum/core" 37 "github.com/ethereumproject/go-ethereum/eth" 38 "github.com/ethereumproject/go-ethereum/eth/downloader" 39 "github.com/ethereumproject/go-ethereum/eth/fetcher" 40 "github.com/ethereumproject/go-ethereum/logger" 41 "github.com/ethereumproject/go-ethereum/logger/glog" 42 "gopkg.in/urfave/cli.v1" 43 ) 44 45 var firstInsertChainEvent = true 46 var gitChainColorFn = func(e *eth.Ethereum) func(string) string { 47 origin, current, height, _, _ := e.Downloader().Progress() 48 if origin > 0 && current >= height { 49 return logger.ColorGreen 50 } 51 return func(s string) string { return s } 52 } 53 54 // greenDisplaySystem is "spec'd" in PR #423 and is a little fancier/more detailed and colorful than basic. 55 var gitDisplaySystem = displayEventHandlers{ 56 { 57 eventT: logEventDownloaderInsertChain, 58 ev: downloader.InsertChainEvent{}, 59 handlers: displayEventHandlerFns{ 60 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 61 switch d := evData.(type) { 62 case downloader.InsertChainEvent: 63 // set up colors 64 colorFn, colorParenFn := logger.ColorGreen, greenParenify 65 if d.Processed == 0 { 66 colorFn, colorParenFn = logger.ColorYellow, yellowParenify 67 } 68 masterChainColorFn := gitChainColorFn(e) 69 prefix := masterChainColorFn("|") + " " + logger.ColorGreen("*") + " Insert " 70 if firstInsertChainEvent && e.Downloader().Synchronising() { 71 glog.D(logger.Info).Infoln(masterChainColorFn("|") + logger.ColorGreen(`\`)) 72 firstInsertChainEvent = false 73 } else if firstInsertChainEvent { 74 // downloader "finishes" before chain inserted function has finished writing 75 prefix = logger.ColorGreen("'*") + " Inserted " 76 firstInsertChainEvent = true 77 } 78 79 glog.D(logger.Info).Infof(prefix+colorFn("blocks")+"=%s "+colorFn("◼")+"=%s "+colorFn("took")+"=%s", 80 colorParenFn(fmt.Sprintf("processed=%4d queued=%4d ignored=%4d txs=%4d", d.Processed, d.Queued, d.Ignored, d.TxCount)), 81 colorParenFn(fmt.Sprintf("n=%8d hash=%s… time=%v ago", d.LastNumber, d.LastHash.Hex()[:9], time.Since(d.LatestBlockTime).Round(time.Millisecond))), 82 colorParenFn(fmt.Sprintf("%v", d.Elasped.Round(time.Millisecond))), 83 ) 84 if bool(glog.D(logger.Info)) { 85 chainEventLastSent = time.Now() 86 } 87 } 88 }, 89 }, 90 }, 91 { 92 eventT: logEventDownloaderInsertHeaderChain, 93 ev: downloader.InsertHeaderChainEvent{}, 94 handlers: displayEventHandlerFns{ 95 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 96 if ctx.GlobalInt(DisplayFlag.Name) <= 3 { 97 return 98 } 99 switch d := evData.(type) { 100 case downloader.InsertHeaderChainEvent: 101 masterChainColorFn := gitChainColorFn(e) 102 if firstInsertChainEvent && e.Downloader().Synchronising() { 103 glog.D(logger.Info).Infoln(masterChainColorFn("|") + logger.ColorGreen(`\`)) 104 } 105 firstInsertChainEvent = false 106 glog.D(logger.Info).Infof(masterChainColorFn("|")+" "+logger.ColorGreen("+")+" Insert "+logger.ColorGreen("headers")+"=%s "+logger.ColorGreen("❐")+"=%s"+logger.ColorGreen("took")+"=%s", 107 greenParenify(fmt.Sprintf("processed=%4d ignored=%4d", d.Processed, d.Ignored)), 108 greenParenify(fmt.Sprintf("n=%4d hash=%s…", d.LastNumber, d.LastHash.Hex()[:9])), 109 greenParenify(fmt.Sprintf("%v", d.Elasped.Round(time.Microsecond))), 110 ) 111 if bool(glog.D(logger.Info)) { 112 chainEventLastSent = time.Now() 113 } 114 } 115 }, 116 }, 117 }, 118 { 119 eventT: logEventDownloaderInsertReceiptChain, 120 ev: downloader.InsertReceiptChainEvent{}, 121 handlers: displayEventHandlerFns{ 122 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 123 if ctx.GlobalInt(DisplayFlag.Name) <= 3 { 124 return 125 } 126 switch d := evData.(type) { 127 case downloader.InsertReceiptChainEvent: 128 masterChainColorFn := gitChainColorFn(e) 129 if firstInsertChainEvent && e.Downloader().Synchronising() { 130 glog.D(logger.Info).Infoln(masterChainColorFn("|") + logger.ColorGreen(`\`)) 131 } 132 firstInsertChainEvent = false 133 glog.D(logger.Info).Infof(masterChainColorFn("|")+" "+logger.ColorGreen("=")+" Insert "+logger.ColorGreen("receipts")+"=%s "+logger.ColorGreen("❐")+"=%s"+logger.ColorGreen("took")+"=%s", 134 greenParenify(fmt.Sprintf("processed=%4d ignored=%4d", d.Processed, d.Ignored)), 135 greenParenify(fmt.Sprintf("n=%4d hash=%s…", d.LastNumber, d.LastHash.Hex()[:9])), 136 greenParenify(fmt.Sprintf("%v", d.Elasped.Round(time.Microsecond))), 137 ) 138 if bool(glog.D(logger.Info)) { 139 chainEventLastSent = time.Now() 140 } 141 } 142 }, 143 }, 144 }, 145 { 146 eventT: logEventFetcherInsert, 147 ev: fetcher.FetcherInsertBlockEvent{}, 148 handlers: displayEventHandlerFns{ 149 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 150 switch d := evData.(type) { 151 case fetcher.FetcherInsertBlockEvent: 152 glog.D(logger.Info).Infof(logger.ColorGreen("*")+" Import "+logger.ColorGreen("◼")+"=%s "+"peer=%s", 153 greenParenify(fmt.Sprintf("n=%8d hash=%s miner=%s time=%v ago", 154 d.Block.NumberU64(), 155 d.Block.Hash().Hex()[:9], 156 d.Block.Coinbase().Hex()[:9], 157 time.Since(time.Unix(d.Block.Time().Int64(), 0)).Round(time.Millisecond))), 158 greenParenify(d.Peer), 159 ) 160 if bool(glog.D(logger.Info)) { 161 chainEventLastSent = time.Now() 162 } 163 } 164 }, 165 }, 166 }, 167 { 168 eventT: logEventCoreChainInsertSide, 169 ev: core.ChainSideEvent{}, 170 handlers: displayEventHandlerFns{ 171 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 172 switch d := evData.(type) { 173 case core.ChainSideEvent: 174 masterChainColorFn := gitChainColorFn(e) 175 glog.D(logger.Info).Infoln(masterChainColorFn("|") + logger.ColorYellow(`\`)) 176 glog.D(logger.Info).Infof(masterChainColorFn("|")+" "+logger.ColorYellow("*")+" Insert "+logger.ColorYellow("forked block")+"=%s", yellowParenify(fmt.Sprintf("n=%8d hash=%s…", d.Block.NumberU64(), d.Block.Hash().Hex()[:9]))) 177 } 178 }, 179 }, 180 }, 181 { 182 eventT: logEventCoreMinedBlock, 183 ev: core.NewMinedBlockEvent{}, 184 handlers: displayEventHandlerFns{ 185 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 186 switch d := evData.(type) { 187 case core.NewMinedBlockEvent: 188 glog.D(logger.Info).Infof(logger.ColorGreen("*) Mined") + " " + logger.ColorGreen("◼") + "=" + greenParenify(fmt.Sprintf("n=%8d hash=%s… coinbase=%s… txs=%3d uncles=%d", 189 d.Block.NumberU64(), 190 d.Block.Hash().Hex()[:9], 191 d.Block.Coinbase().Hex()[:9], 192 len(d.Block.Transactions()), 193 len(d.Block.Uncles()), 194 ))) 195 } 196 }, 197 }, 198 }, 199 { 200 eventT: logEventDownloaderStart, 201 ev: downloader.StartEvent{}, 202 handlers: displayEventHandlerFns{ 203 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 204 if ctx.GlobalInt(DisplayFlag.Name) < 4 { 205 return 206 } 207 switch d := evData.(type) { 208 case downloader.StartEvent: 209 masterChainColorFn := gitChainColorFn(e) 210 s := masterChainColorFn("|") + " " + logger.ColorGreen("~") + " Download " + logger.ColorGreen("start") + " " + greenParenify(fmt.Sprintf("%s", d.Peer)) + " hash=" + greenParenify(d.Hash.Hex()[:9]+"…") + " TD=" + greenParenify(fmt.Sprintf("%v", d.TD)) 211 glog.D(logger.Info).Infoln(s) 212 } 213 }, 214 }, 215 }, 216 { 217 eventT: logEventDownloaderDone, 218 ev: downloader.DoneEvent{}, 219 handlers: displayEventHandlerFns{ 220 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 221 if ctx.GlobalInt(DisplayFlag.Name) < 4 { 222 return 223 } 224 switch d := evData.(type) { 225 case downloader.DoneEvent: 226 masterChainColorFn := gitChainColorFn(e) 227 s := masterChainColorFn("|") + " " + logger.ColorGreen("~") + " Download " + logger.ColorGreen("done") + " " + greenParenify(fmt.Sprintf("%s", d.Peer)) + " hash=" + greenParenify(d.Hash.Hex()[:9]+"…") + " TD=" + greenParenify(fmt.Sprintf("%v", d.TD)) 228 glog.D(logger.Info).Infoln("|" + logger.ColorGreen(`/`)) 229 glog.D(logger.Info).Infoln(s) 230 firstInsertChainEvent = true 231 } 232 }, 233 }, 234 }, 235 { 236 eventT: logEventDownloaderFailed, 237 ev: downloader.FailedEvent{}, 238 handlers: displayEventHandlerFns{ 239 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 240 if ctx.GlobalInt(DisplayFlag.Name) < 4 { 241 return 242 } 243 switch d := evData.(type) { 244 case downloader.FailedEvent: 245 masterChainColorFn := gitChainColorFn(e) 246 s := masterChainColorFn("|") + " " + logger.ColorYellow("~") + " Download " + logger.ColorYellow("fail") + " " + yellowParenify(fmt.Sprintf("%s", d.Peer)) + " " + logger.ColorYellow("err") + "=" + yellowParenify(d.Err.Error()) 247 if downloader.ErrWasRequested(d.Err) { 248 glog.D(logger.Info).Infoln(s) 249 } else { 250 glog.D(logger.Warn).Warnln(s) 251 } 252 firstInsertChainEvent = true 253 } 254 }, 255 }, 256 }, 257 { 258 eventT: logEventInterval, 259 handlers: displayEventHandlerFns{ 260 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 261 if (ctx.GlobalInt(DisplayFlag.Name) <= 3 && e.Downloader().GetMode() == downloader.FastSync) || time.Since(chainEventLastSent) > time.Duration(time.Second*time.Duration(int32(tickerInterval.Seconds()))) { 262 currentBlockNumber = PrintStatusGit(e, tickerInterval, ctx.GlobalInt(aliasableName(MaxPeersFlag.Name, ctx))) 263 } 264 }, 265 }, 266 }, 267 { 268 eventT: logEventBefore, 269 handlers: displayEventHandlerFns{ 270 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 271 currentBlockNumber = e.BlockChain().CurrentFastBlock().NumberU64() 272 }, 273 }, 274 }, 275 } 276 277 // PrintStatusGreen implements the displayEventHandlerFn interface 278 var PrintStatusGit = func(e *eth.Ethereum, tickerInterval time.Duration, maxPeers int) uint64 { 279 lenPeers := e.Downloader().GetPeers().Len() 280 281 rtt, ttl, conf := e.Downloader().Qos() 282 confS := fmt.Sprintf("%01.2f", conf) 283 qosDisplay := fmt.Sprintf("rtt=%v ttl=%v conf=%s", rtt.Round(time.Millisecond), ttl.Round(time.Millisecond), confS) 284 285 _, current, height, _, _ := e.Downloader().Progress() // origin, current, height, pulled, known 286 mode := e.Downloader().GetMode() 287 288 blockchain := e.BlockChain() 289 currentBlockHex := blockchain.CurrentBlock().Hash().Hex() 290 if mode == downloader.FastSync { 291 fb := e.BlockChain().CurrentFastBlock() 292 current = fb.NumberU64() 293 currentBlockHex = fb.Hash().Hex() 294 } 295 296 // Get our head block 297 // Discover -> not synchronising (searching for peers) 298 // FullSync/FastSync -> synchronising 299 // Import -> synchronising, at full height 300 fOfHeight := fmt.Sprintf("%7d", height) 301 302 // Calculate and format percent sync of known height 303 heightRatio := float64(current) / float64(height) 304 heightRatio = heightRatio * 100 305 fHeightRatio := fmt.Sprintf("%4.2f%%", heightRatio) 306 307 // Wait until syncing because real dl mode will not be engaged until then 308 if currentMode == lsModeImport { 309 fOfHeight = "" // strings.Repeat(" ", 12) 310 fHeightRatio = "" // strings.Repeat(" ", 7) 311 } 312 if height == 0 { 313 fOfHeight = "" // strings.Repeat(" ", 12) 314 fHeightRatio = "" // strings.Repeat(" ", 7) 315 } 316 317 // Calculate block stats for interval 318 numBlocksDiff := current - currentBlockNumber 319 numTxsDiff := 0 320 mGas := new(big.Int) 321 322 var numBlocksDiffPerSecond uint64 323 var numTxsDiffPerSecond int 324 var mGasPerSecond = new(big.Int) 325 326 var dominoGraph string 327 var nDom int 328 if numBlocksDiff > 0 && numBlocksDiff != current { 329 for i := currentBlockNumber + 1; i <= current; i++ { 330 b := blockchain.GetBlockByNumber(i) 331 if b != nil { 332 txLen := b.Transactions().Len() 333 // Add to tallies 334 numTxsDiff += txLen 335 mGas = new(big.Int).Add(mGas, b.GasUsed()) 336 // Domino effect 337 if currentMode == lsModeImport { 338 if txLen > len(dominoes)-1 { 339 // prevent slice out of bounds 340 txLen = len(dominoes) - 1 341 } 342 if nDom <= 20 { 343 dominoGraph += dominoes[txLen] 344 } 345 nDom++ 346 } 347 } 348 } 349 if nDom > 20 { 350 dominoGraph += "…" 351 } 352 } 353 dominoGraph = logger.ColorGreen(dominoGraph) 354 355 // Convert to per-second stats 356 // FIXME(?): Some degree of rounding will happen. 357 // For example, if interval is 10s and we get 6 blocks imported in that span, 358 // stats will show '0' blocks/second. Looks a little strange; but on the other hand, 359 // precision costs visual space, and normally just looks weird when starting up sync or 360 // syncing slowly. 361 numBlocksDiffPerSecond = numBlocksDiff / uint64(tickerInterval.Seconds()) 362 363 // Don't show initial current / per second val 364 if currentBlockNumber == 0 { 365 numBlocksDiffPerSecond = 0 366 numBlocksDiff = 0 367 } 368 369 // Divide by interval to yield per-second stats 370 numTxsDiffPerSecond = numTxsDiff / int(tickerInterval.Seconds()) 371 mGasPerSecond = new(big.Int).Div(mGas, big.NewInt(int64(tickerInterval.Seconds()))) 372 mGasPerSecond = new(big.Int).Div(mGasPerSecond, big.NewInt(1000000)) 373 mGasPerSecondI := mGasPerSecond.Int64() 374 375 // Format head block hex for printing (eg. d4e…fa3) 376 cbhexstart := currentBlockHex[:9] // trim off '0x' prefix 377 378 localHeadHeight := fmt.Sprintf("#%7d", current) 379 localHeadHex := fmt.Sprintf("%s…", cbhexstart) 380 peersOfMax := fmt.Sprintf("%2d/%2d peers", lenPeers, maxPeers) 381 domOrHeight := fOfHeight + " " + fHeightRatio 382 if len(strings.Replace(domOrHeight, " ", "", -1)) != 0 { 383 domOrHeight = logger.ColorGreen("height") + "=" + greenParenify(domOrHeight) 384 } else { 385 domOrHeight = "" 386 } 387 var blocksprocesseddisplay string 388 qosDisplayable := logger.ColorGreen("qos") + "=" + greenParenify(qosDisplay) 389 if currentMode != lsModeImport { 390 blocksprocesseddisplay = logger.ColorGreen("~") + greenParenify(fmt.Sprintf("%4d blks %4d txs %2d mgas "+logger.ColorGreen("/sec"), numBlocksDiffPerSecond, numTxsDiffPerSecond, mGasPerSecondI)) 391 } else { 392 blocksprocesseddisplay = logger.ColorGreen("+") + greenParenify(fmt.Sprintf("%4d blks %4d txs %8d mgas", numBlocksDiff, numTxsDiff, mGas.Uint64())) 393 domOrHeight = dominoGraph 394 qosDisplayable = "" 395 } 396 if currentMode == lsModeDiscover { 397 blocksprocesseddisplay = "" 398 } 399 400 // Log to ERROR. 401 headDisplay := greenParenify(localHeadHeight + " " + localHeadHex) 402 peerDisplay := greenParenify(peersOfMax) 403 404 modeIcon := logger.ColorGreen(lsModeIcon[currentMode]) 405 if currentMode == lsModeDiscover { 406 // TODO: spin me 407 modeIcon = lsModeDiscoverSpinners[0] 408 } 409 modeIcon = logger.ColorGreen(modeIcon) 410 411 // This allows maximum user optionality for desired integration with rest of event-based logging. 412 glog.D(logger.Warn).Infof("%s "+modeIcon+"%s %s "+logger.ColorGreen("✌︎︎︎")+"%s %s %s", 413 logger.ColorBlue(": "+currentMode.String()), headDisplay, blocksprocesseddisplay, peerDisplay, domOrHeight, qosDisplayable) 414 return current 415 }