github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/cmd/geth/log_display_green.go (about) 1 // --- 2 //2017-12-19 08:55:03 Discover ➫⟪# 0 0xd4e5674…⟫ ~⟪ 0 blks 0 txs 0 mgas /sec⟫ ✌︎︎︎⟪ 1/25 peers⟫ qos=⟪rtt=18s ttl=1m0s conf=1.00⟫ 3 //2017-12-19 08:55:17 ◼⋯⋯⬇ Start ⟪Peer id=931f21921fcc7654 eth/63 [Parity/v1.8.3-beta-b49c44a-20171114/x86_64-linux-gnu/rustc1.21.0] [hs 0.00/s, bs 0.00/s, rs 0.00/s, ss 0.00/s, miss 0, rtt 20s]⟫ hash=⟪0xc5ea430…⟫ TD=⟪185549045030301150788⟫ 4 //2017-12-19 08:55:19 ◼⋯⋯❐ Insert headers=⟪processed= 0 ignored= 192⟫ ❐=⟪n=1836399 hash=0x1ecf991…⟫took=⟪73.546ms⟫ 5 //2017-12-19 08:55:20 ◼⋯⋯❐ Insert headers=⟪processed= 0 ignored= 192⟫ ❐=⟪n=1836591 hash=0xcff7c3c…⟫took=⟪275.686ms⟫ 6 //2017-12-19 08:57:25 ◼⋯⋯⬇ Fail ⟪Peer id=931f21921fcc7654 eth/63 [Parity/v1.8.3-beta-b49c44a-20171114/x86_64-linux-gnu/rustc1.21.0] [hs 211.71/s, bs 124.20/s, rs 184.06/s, ss 735.50/s, miss 0, rtt 1.512187158s]⟫ err=⟪content processing canceled (requested)⟫ 7 //2017-12-19 09:00:43 ◼⋯⋯⬇ Start ⟪Peer id=f30acc4f9c1a4369 eth/63 [Parity/v1.8.4-beta-c74c8c1-20171211/x86_64-linux-gnu/rustc1.22.1] [hs 0.00/s, bs 0.00/s, rs 0.00/s, ss 0.00/s, miss 0, rtt 20s]⟫ hash=⟪0x26f9a91…⟫ TD=⟪185552382866154347587⟫ 8 //2017-12-19 09:00:46 Sync ︎◉⟪#5043160 0xed71bef…⟫ ~⟪ 0 blks 0 txs 0 mgas /sec⟫ ✌︎︎︎⟪ 5/25 peers⟫ height=⟪5047421 99.92%⟫ qos=⟪rtt=15.942s ttl=1m0s conf=0.70⟫ 9 //2017-12-19 09:00:51 ◼⋯⋯◼ Insert blocks=⟪processed= 48 queued= 0 ignored= 0 txs= 341⟫ ◼=⟪n= 5043208 hash=0x195123c… time=16h55m40.639s ago⟫ took=⟪5.692s⟫ 10 //2017-12-19 09:01:47 Sync ︎◉⟪#5044175 0xedb389d…⟫ ~⟪ 16 blks 142 txs 3 mgas /sec⟫ ✌︎︎︎⟪ 8/25 peers⟫ height=⟪5047421 99.94%⟫ qos=⟪rtt=9.585s ttl=36.603s conf=0.87⟫ 11 //2017-12-19 09:02:43 ◼⋯⋯◼ Insert blocks=⟪processed=2048 queued= 0 ignored= 0 txs=17899⟫ ◼=⟪n= 5045256 hash=0xcf3d3fb… time=8h49m5.014s ago⟫ took=⟪1m51.251s⟫ 12 //2017-12-19 09:03:47 Sync ︎◉⟪#5046394 0x8b10bdd…⟫ ~⟪ 36 blks 306 txs 9 mgas /sec⟫ ✌︎︎︎⟪11/25 peers⟫ height=⟪5047421 99.98%⟫ qos=⟪rtt=6.695s ttl=22.328s conf=1.00⟫ 13 //2017-12-19 09:04:43 ◼⋯⋯◼ Insert blocks=⟪processed=2048 queued= 0 ignored= 0 txs=18124⟫ ◼=⟪n= 5047304 hash=0xc0b4780… time=33m45.455s ago⟫ took=⟪2m0.462s⟫ 14 //2017-12-19 09:04:50 ◼⋯⋯⬇ Done ⟪Peer id=f30acc4f9c1a4369 eth/63 [Parity/v1.8.4-beta-c74c8c1-20171211/x86_64-linux-gnu/rustc1.22.1] [hs 813.97/s, bs 295.27/s, rs 0.00/s, ss 0.00/s, miss 0, rtt 1.918361657s]⟫ hash=⟪0x26f9a91…⟫ TD=⟪185552382866154347587⟫ 15 //2017-12-19 09:04:50 ◼⋯⋯◼ Insert blocks=⟪processed= 118 queued= 0 ignored= 0 txs=1183⟫ ◼=⟪n= 5047422 hash=0xc47a4fc… time=4m24.711s ago⟫ took=⟪7.258s⟫ 16 //2017-12-19 09:04:51 ◼⋯⋯⬇ Start ⟪Peer id=f30acc4f9c1a4369 eth/63 [Parity/v1.8.4-beta-c74c8c1-20171211/x86_64-linux-gnu/rustc1.22.1] [hs 0.00/s, bs 0.00/s, rs 0.00/s, ss 0.00/s, miss 0, rtt 1.918361657s]⟫ hash=⟪0x249c344…⟫ TD=⟪185554240788446349916⟫ 17 //2017-12-19 09:04:52 ◼⋯⋯◼ Insert blocks=⟪processed= 4 queued= 0 ignored= 0 txs= 53⟫ ◼=⟪n= 5047426 hash=0x6aff1b9… time=3m21.897s ago⟫ took=⟪185ms⟫ 18 //2017-12-19 09:04:53 ◼⋯⋯⬇ Done ⟪Peer id=f30acc4f9c1a4369 eth/63 [Parity/v1.8.4-beta-c74c8c1-20171211/x86_64-linux-gnu/rustc1.22.1] [hs 0.00/s, bs 1.18/s, rs 0.00/s, ss 0.00/s, miss 0, rtt 1.743539409s]⟫ hash=⟪0x249c344…⟫ TD=⟪185554240788446349916⟫ 19 //2017-12-19 09:04:53 ◼⋯⋯◼ Insert blocks=⟪processed= 11 queued= 0 ignored= 0 txs= 119⟫ ◼=⟪n= 5047437 hash=0x3950d3d… time=1m27.504s ago⟫ took=⟪735ms⟫ 20 //2017-12-19 09:09:53 ◼⋯⋯◼ Insert blocks=⟪processed= 13 queued= 0 ignored= 0 txs= 124⟫ ◼=⟪n= 5047453 hash=0xff69a28… time=19.599s ago⟫ took=⟪630ms⟫ 21 //2017-12-19 09:10:11 ◼⋯⋯◼ Insert blocks=⟪processed= 1 queued= 0 ignored= 0 txs= 1⟫ ◼=⟪n= 5047454 hash=0xd03268a… time=34.122s ago⟫ took=⟪8ms⟫ 22 //2017-12-19 09:10:18 ◼⋯⋯◼ Insert blocks=⟪processed= 1 queued= 0 ignored= 0 txs= 7⟫ ◼=⟪n= 5047455 hash=0x1364b57… time=13.649s ago⟫ took=⟪17ms⟫ 23 //2017-12-19 09:10:25 ◼⋯⋯◼ Insert blocks=⟪processed= 1 queued= 0 ignored= 0 txs= 6⟫ ◼=⟪n= 5047456 hash=0x00ee977… time=12.328s ago⟫ took=⟪23ms⟫ 24 // --- 25 26 package main 27 28 import ( 29 "fmt" 30 "math/big" 31 "strings" 32 "time" 33 34 "github.com/ethereumproject/go-ethereum/core" 35 "github.com/ethereumproject/go-ethereum/eth" 36 "github.com/ethereumproject/go-ethereum/eth/downloader" 37 "github.com/ethereumproject/go-ethereum/eth/fetcher" 38 "github.com/ethereumproject/go-ethereum/logger" 39 "github.com/ethereumproject/go-ethereum/logger/glog" 40 "gopkg.in/urfave/cli.v1" 41 ) 42 43 var lsModeIcon = []string{ 44 "", 45 "︎◉", 46 "◎", 47 "▶︎", 48 } 49 50 var dominoes = []string{"🁣", "🁤", "🁥", "🁦", "🁭", "🁴", "🁻", "🁼", "🂃", "🂄", "🂋", "🂌", "🂓"} // 🁣🁤🁥🁦🁭🁴🁻🁼🂃🂄🂋🂌🂓 51 var chainIcon = "◼⋯⋯" + logger.ColorGreen("◼") 52 var forkIcon = "◼⋯⦦" + logger.ColorGreen("◼") 53 var headerIcon = "◼⋯⋯" + logger.ColorGreen("❐") 54 var downloaderIconStart = "◼⋯⋯" + logger.ColorGreen("⬇") 55 var downloaderIconDone = "◼⋯⋯" + logger.ColorGreen("✔︎") 56 var downloaderIconFail = "◼⋯⋯" + logger.ColorRed("✕") 57 var minedIcon = "◼⋯⋯" + logger.ColorGreen("⟠") 58 var lsModeDiscoverSpinners = []string{"➫", "➬", "➭"} 59 var downloadingFrom = "" 60 61 func greenParenify(s string) string { 62 return logger.ColorGreen("⟪") + s + logger.ColorGreen("⟫") 63 } 64 func redParenify(s string) string { 65 return logger.ColorRed("⟪") + s + logger.ColorRed("⟫") 66 } 67 func yellowParenify(s string) string { 68 return logger.ColorYellow("⟪") + s + logger.ColorYellow("⟫") 69 } 70 func prefix(ev interface{}, e *eth.Ethereum) string { 71 //s := "⋮⫟⫠⫶|"⇶⇉⇣⇣⥥⤹↙⤹⎯⏐↵↳⤶⤷⤵↔ 72 switch d := ev.(type) { 73 case downloader.StartEvent: 74 downloadingFrom = d.Peer.String() 75 return logger.ColorGreen(`⤹ `) 76 case downloader.DoneEvent: 77 downloadingFrom = "" 78 return logger.ColorGreen(`⤷ `) 79 case downloader.FailedEvent: 80 downloadingFrom = "" 81 return logger.ColorRed(`⤷ `) 82 case downloader.InsertChainEvent: 83 return logger.ColorYellow(`⇣ `) 84 //case fetcher.FetcherInsertBlockEvent: 85 default: 86 } 87 return "" 88 } 89 90 // greenDisplaySystem is "spec'd" in PR #423 and is a little fancier/more detailed and colorful than basic. 91 var greenDisplaySystem = displayEventHandlers{ 92 { 93 eventT: logEventDownloaderInsertChain, 94 ev: downloader.InsertChainEvent{}, 95 handlers: displayEventHandlerFns{ 96 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 97 switch d := evData.(type) { 98 case downloader.InsertChainEvent: 99 colorFn, colorParenFn := logger.ColorGreen, greenParenify 100 if d.Processed == 0 { 101 colorFn, colorParenFn = logger.ColorYellow, yellowParenify 102 } 103 glog.D(logger.Info).Infof(prefix(d, e)+chainIcon+" Insert "+colorFn("blocks")+"=%s "+colorFn("◼")+"=%s "+colorFn("took")+"=%s", 104 colorParenFn(fmt.Sprintf("processed=%4d queued=%4d ignored=%4d txs=%4d", d.Processed, d.Queued, d.Ignored, d.TxCount)), 105 colorParenFn(fmt.Sprintf("n=%8d hash=%s… time=%v ago", d.LastNumber, d.LastHash.Hex()[:9], time.Since(d.LatestBlockTime).Round(time.Millisecond))), 106 colorParenFn(fmt.Sprintf("%v", d.Elasped.Round(time.Millisecond))), 107 ) 108 if bool(glog.D(logger.Info)) { 109 chainEventLastSent = time.Now() 110 } 111 } 112 }, 113 }, 114 }, 115 { 116 eventT: logEventFetcherInsert, 117 ev: fetcher.FetcherInsertBlockEvent{}, 118 handlers: displayEventHandlerFns{ 119 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 120 switch d := evData.(type) { 121 case fetcher.FetcherInsertBlockEvent: 122 glog.D(logger.Info).Infof(prefix(d, e)+chainIcon+" Import "+logger.ColorGreen("◼")+"=%s "+"peer=%s", 123 greenParenify(fmt.Sprintf("n=%8d hash=%s miner=%s time=%v ago", 124 d.Block.NumberU64(), 125 d.Block.Hash().Hex()[:9], 126 d.Block.Coinbase().Hex()[:9], 127 time.Since(time.Unix(d.Block.Time().Int64(), 0)).Round(time.Millisecond))), 128 greenParenify(d.Peer), 129 ) 130 if bool(glog.D(logger.Info)) { 131 chainEventLastSent = time.Now() 132 } 133 } 134 }, 135 }, 136 }, 137 { 138 eventT: logEventCoreChainInsertSide, 139 ev: core.ChainSideEvent{}, 140 handlers: displayEventHandlerFns{ 141 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 142 switch d := evData.(type) { 143 case core.ChainSideEvent: 144 glog.D(logger.Info).Infof(prefix(d, e)+forkIcon+" Insert "+logger.ColorGreen("forked block")+"=%s", greenParenify(fmt.Sprintf("n=%8d hash=%s…", d.Block.NumberU64(), d.Block.Hash().Hex()[:9]))) 145 } 146 }, 147 }, 148 }, 149 { 150 eventT: logEventCoreHeaderChainInsert, 151 ev: core.HeaderChainInsertEvent{}, 152 handlers: displayEventHandlerFns{ 153 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 154 switch d := evData.(type) { 155 case core.HeaderChainInsertEvent: 156 glog.D(logger.Info).Infof(prefix(d, e)+headerIcon+" Insert "+logger.ColorGreen("headers")+"=%s "+logger.ColorGreen("❐")+"=%s"+logger.ColorGreen("took")+"=%s", 157 greenParenify(fmt.Sprintf("processed=%4d ignored=%4d", d.Processed, d.Ignored)), 158 greenParenify(fmt.Sprintf("n=%4d hash=%s…", d.LastNumber, d.LastHash.Hex()[:9])), 159 greenParenify(fmt.Sprintf("%v", d.Elasped.Round(time.Microsecond))), 160 ) 161 if bool(glog.D(logger.Info)) { 162 chainEventLastSent = time.Now() 163 } 164 } 165 }, 166 }, 167 }, 168 { 169 eventT: logEventCoreMinedBlock, 170 ev: core.NewMinedBlockEvent{}, 171 handlers: displayEventHandlerFns{ 172 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 173 switch d := evData.(type) { 174 case core.NewMinedBlockEvent: 175 glog.D(logger.Info).Infof(prefix(d, e) + minedIcon + " Mined " + logger.ColorGreen("◼") + "=" + greenParenify(fmt.Sprintf("n=%8d hash=%s… coinbase=%s… txs=%3d uncles=%d", 176 d.Block.NumberU64(), 177 d.Block.Hash().Hex()[:9], 178 d.Block.Coinbase().Hex()[:9], 179 len(d.Block.Transactions()), 180 len(d.Block.Uncles()), 181 ))) 182 } 183 }, 184 }, 185 }, 186 { 187 eventT: logEventDownloaderStart, 188 ev: downloader.StartEvent{}, 189 handlers: displayEventHandlerFns{ 190 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 191 switch d := evData.(type) { 192 case downloader.StartEvent: 193 s := prefix(d, e) + downloaderIconStart + " Start " + greenParenify(fmt.Sprintf("%s", d.Peer)) + " hash=" + greenParenify(d.Hash.Hex()[:9]+"…") + " TD=" + greenParenify(fmt.Sprintf("%v", d.TD)) 194 glog.D(logger.Info).Infoln(s) 195 } 196 }, 197 }, 198 }, 199 { 200 eventT: logEventDownloaderDone, 201 ev: downloader.DoneEvent{}, 202 handlers: displayEventHandlerFns{ 203 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 204 switch d := evData.(type) { 205 case downloader.DoneEvent: 206 s := prefix(d, e) + downloaderIconDone + " Done " + greenParenify(fmt.Sprintf("%s", d.Peer)) + " hash=" + greenParenify(d.Hash.Hex()[:9]+"…") + " TD=" + greenParenify(fmt.Sprintf("%v", d.TD)) 207 glog.D(logger.Info).Infoln(s) 208 } 209 }, 210 }, 211 }, 212 { 213 eventT: logEventDownloaderFailed, 214 ev: downloader.FailedEvent{}, 215 handlers: displayEventHandlerFns{ 216 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 217 switch d := evData.(type) { 218 case downloader.FailedEvent: 219 s := prefix(d, e) + downloaderIconFail + " Fail " + redParenify(fmt.Sprintf("%s", d.Peer)) + " " + logger.ColorRed("err") + "=" + redParenify(d.Err.Error()) 220 glog.D(logger.Info).Warnln(s) 221 } 222 }, 223 }, 224 }, 225 { 226 eventT: logEventInterval, 227 handlers: displayEventHandlerFns{ 228 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 229 if time.Since(chainEventLastSent) > time.Duration(time.Second*time.Duration(int32(tickerInterval.Seconds()))) { 230 currentBlockNumber = PrintStatusGreen(e, tickerInterval, ctx.GlobalInt(aliasableName(MaxPeersFlag.Name, ctx))) 231 } 232 }, 233 }, 234 }, 235 { 236 eventT: logEventBefore, 237 handlers: displayEventHandlerFns{ 238 func(ctx *cli.Context, e *eth.Ethereum, evData interface{}, tickerInterval time.Duration) { 239 }, 240 }, 241 }, 242 } 243 244 // PrintStatusGreen implements the displayEventHandlerFn interface 245 var PrintStatusGreen = func(e *eth.Ethereum, tickerInterval time.Duration, maxPeers int) uint64 { 246 lenPeers := e.Downloader().GetPeers().Len() 247 248 rtt, ttl, conf := e.Downloader().Qos() 249 confS := fmt.Sprintf("%01.2f", conf) 250 qosDisplay := fmt.Sprintf("rtt=%v ttl=%v conf=%s", rtt.Round(time.Millisecond), ttl.Round(time.Millisecond), confS) 251 252 _, current, height, _, _ := e.Downloader().Progress() // origin, current, height, pulled, known 253 mode := e.Downloader().GetMode() 254 if mode == downloader.FastSync { 255 current = e.BlockChain().CurrentFastBlock().NumberU64() 256 } 257 258 // Get our head block 259 blockchain := e.BlockChain() 260 currentBlockHex := blockchain.CurrentBlock().Hash().Hex() 261 262 // Discover -> not synchronising (searching for peers) 263 // FullSync/FastSync -> synchronising 264 // Import -> synchronising, at full height 265 fOfHeight := fmt.Sprintf("%7d", height) 266 267 // Calculate and format percent sync of known height 268 heightRatio := float64(current) / float64(height) 269 heightRatio = heightRatio * 100 270 fHeightRatio := fmt.Sprintf("%4.2f%%", heightRatio) 271 272 // Wait until syncing because real dl mode will not be engaged until then 273 if currentMode == lsModeImport { 274 fOfHeight = "" // strings.Repeat(" ", 12) 275 fHeightRatio = "" // strings.Repeat(" ", 7) 276 } 277 if height == 0 { 278 fOfHeight = "" // strings.Repeat(" ", 12) 279 fHeightRatio = "" // strings.Repeat(" ", 7) 280 } 281 282 // Calculate block stats for interval 283 numBlocksDiff := current - currentBlockNumber 284 numTxsDiff := 0 285 mGas := new(big.Int) 286 287 var numBlocksDiffPerSecond uint64 288 var numTxsDiffPerSecond int 289 var mGasPerSecond = new(big.Int) 290 291 var dominoGraph string 292 var nDom int 293 if numBlocksDiff > 0 && numBlocksDiff != current { 294 for i := currentBlockNumber + 1; i <= current; i++ { 295 b := blockchain.GetBlockByNumber(i) 296 if b != nil { 297 txLen := b.Transactions().Len() 298 // Add to tallies 299 numTxsDiff += txLen 300 mGas = new(big.Int).Add(mGas, b.GasUsed()) 301 // Domino effect 302 if currentMode == lsModeImport { 303 if txLen > len(dominoes)-1 { 304 // prevent slice out of bounds 305 txLen = len(dominoes) - 1 306 } 307 if nDom <= 20 { 308 dominoGraph += dominoes[txLen] 309 } 310 nDom++ 311 } 312 } 313 } 314 if nDom > 20 { 315 dominoGraph += "…" 316 } 317 } 318 dominoGraph = logger.ColorGreen(dominoGraph) 319 320 // Convert to per-second stats 321 // FIXME(?): Some degree of rounding will happen. 322 // For example, if interval is 10s and we get 6 blocks imported in that span, 323 // stats will show '0' blocks/second. Looks a little strange; but on the other hand, 324 // precision costs visual space, and normally just looks weird when starting up sync or 325 // syncing slowly. 326 numBlocksDiffPerSecond = numBlocksDiff / uint64(tickerInterval.Seconds()) 327 328 // Don't show initial current / per second val 329 if currentBlockNumber == 0 { 330 numBlocksDiffPerSecond = 0 331 numBlocksDiff = 0 332 } 333 334 // Divide by interval to yield per-second stats 335 numTxsDiffPerSecond = numTxsDiff / int(tickerInterval.Seconds()) 336 mGasPerSecond = new(big.Int).Div(mGas, big.NewInt(int64(tickerInterval.Seconds()))) 337 mGasPerSecond = new(big.Int).Div(mGasPerSecond, big.NewInt(1000000)) 338 mGasPerSecondI := mGasPerSecond.Int64() 339 340 // Format head block hex for printing (eg. d4e…fa3) 341 cbhexstart := currentBlockHex[:9] // trim off '0x' prefix 342 343 localHeadHeight := fmt.Sprintf("#%7d", current) 344 localHeadHex := fmt.Sprintf("%s…", cbhexstart) 345 peersOfMax := fmt.Sprintf("%2d/%2d peers", lenPeers, maxPeers) 346 domOrHeight := fOfHeight + " " + fHeightRatio 347 if len(strings.Replace(domOrHeight, " ", "", -1)) != 0 { 348 domOrHeight = logger.ColorGreen("height") + "=" + greenParenify(domOrHeight) 349 } else { 350 domOrHeight = "" 351 } 352 var blocksprocesseddisplay string 353 qosDisplayable := logger.ColorGreen("qos") + "=" + greenParenify(qosDisplay) 354 if currentMode != lsModeImport { 355 blocksprocesseddisplay = logger.ColorGreen("~") + greenParenify(fmt.Sprintf("%4d blks %4d txs %2d mgas "+logger.ColorGreen("/sec"), numBlocksDiffPerSecond, numTxsDiffPerSecond, mGasPerSecondI)) 356 } else { 357 blocksprocesseddisplay = logger.ColorGreen("+") + greenParenify(fmt.Sprintf("%4d blks %4d txs %8d mgas", numBlocksDiff, numTxsDiff, mGas.Uint64())) 358 domOrHeight = dominoGraph 359 qosDisplayable = "" 360 } 361 if currentMode == lsModeDiscover { 362 blocksprocesseddisplay = "" 363 } 364 365 // Log to ERROR. 366 headDisplay := greenParenify(localHeadHeight + " " + localHeadHex) 367 peerDisplay := greenParenify(peersOfMax) 368 369 modeIcon := logger.ColorGreen(lsModeIcon[currentMode]) 370 if currentMode == lsModeDiscover { 371 // TODO: spin me 372 modeIcon = lsModeDiscoverSpinners[0] 373 } 374 modeIcon = logger.ColorGreen(modeIcon) 375 376 // This allows maximum user optionality for desired integration with rest of event-based logging. 377 glog.D(logger.Warn).Infof("%s "+modeIcon+"%s %s "+logger.ColorGreen("✌︎︎︎")+"%s %s %s", 378 logger.ColorBlue(currentMode.String()), headDisplay, blocksprocesseddisplay, peerDisplay, domOrHeight, qosDisplayable) 379 return current 380 }