github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/cmd/geth/logtestcmd_active.go (about) 1 //go:build integrationtests 2 3 // Copyright 2023 The go-ethereum Authors 4 // This file is part of go-ethereum. 5 // 6 // go-ethereum is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // (at your option) any later version. 10 // 11 // go-ethereum is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 18 19 package main 20 21 import ( 22 "errors" 23 "fmt" 24 "math" 25 "math/big" 26 "time" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/log" 30 "github.com/holiman/uint256" 31 "github.com/urfave/cli/v2" 32 ) 33 34 var logTestCommand = &cli.Command{ 35 Action: logTest, 36 Name: "logtest", 37 Usage: "Print some log messages", 38 ArgsUsage: " ", 39 Description: ` 40 This command is only meant for testing. 41 `} 42 43 type customQuotedStringer struct { 44 } 45 46 func (c customQuotedStringer) String() string { 47 return "output with 'quotes'" 48 } 49 50 // logTest is an entry point which spits out some logs. This is used by testing 51 // to verify expected outputs 52 func logTest(ctx *cli.Context) error { 53 { // big.Int 54 ba, _ := new(big.Int).SetString("111222333444555678999", 10) // "111,222,333,444,555,678,999" 55 bb, _ := new(big.Int).SetString("-111222333444555678999", 10) // "-111,222,333,444,555,678,999" 56 bc, _ := new(big.Int).SetString("11122233344455567899900", 10) // "11,122,233,344,455,567,899,900" 57 bd, _ := new(big.Int).SetString("-11122233344455567899900", 10) // "-11,122,233,344,455,567,899,900" 58 log.Info("big.Int", "111,222,333,444,555,678,999", ba) 59 log.Info("-big.Int", "-111,222,333,444,555,678,999", bb) 60 log.Info("big.Int", "11,122,233,344,455,567,899,900", bc) 61 log.Info("-big.Int", "-11,122,233,344,455,567,899,900", bd) 62 } 63 { //uint256 64 ua, _ := uint256.FromDecimal("111222333444555678999") 65 ub, _ := uint256.FromDecimal("11122233344455567899900") 66 log.Info("uint256", "111,222,333,444,555,678,999", ua) 67 log.Info("uint256", "11,122,233,344,455,567,899,900", ub) 68 } 69 { // int64 70 log.Info("int64", "1,000,000", int64(1000000)) 71 log.Info("int64", "-1,000,000", int64(-1000000)) 72 log.Info("int64", "9,223,372,036,854,775,807", int64(math.MaxInt64)) 73 log.Info("int64", "-9,223,372,036,854,775,808", int64(math.MinInt64)) 74 } 75 { // uint64 76 log.Info("uint64", "1,000,000", uint64(1000000)) 77 log.Info("uint64", "18,446,744,073,709,551,615", uint64(math.MaxUint64)) 78 } 79 { // Special characters 80 log.Info("Special chars in value", "key", "special \r\n\t chars") 81 log.Info("Special chars in key", "special \n\t chars", "value") 82 83 log.Info("nospace", "nospace", "nospace") 84 log.Info("with space", "with nospace", "with nospace") 85 86 log.Info("Bash escapes in value", "key", "\u001b[1G\u001b[K\u001b[1A") 87 log.Info("Bash escapes in key", "\u001b[1G\u001b[K\u001b[1A", "value") 88 89 log.Info("Bash escapes in message \u001b[1G\u001b[K\u001b[1A end", "key", "value") 90 91 colored := fmt.Sprintf("\u001B[%dmColored\u001B[0m[", 35) 92 log.Info(colored, colored, colored) 93 err := errors.New("this is an 'error'") 94 log.Info("an error message with quotes", "error", err) 95 } 96 { // Custom Stringer() - type 97 log.Info("Custom Stringer value", "2562047h47m16.854s", common.PrettyDuration(time.Duration(9223372036854775807))) 98 var c customQuotedStringer 99 log.Info("a custom stringer that emits quoted text", "output", c) 100 } 101 { // Multi-line message 102 log.Info("A message with wonky \U0001F4A9 characters") 103 log.Info("A multiline message \nINFO [10-18|14:11:31.106] with wonky characters \U0001F4A9") 104 log.Info("A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above") 105 } 106 { // Miscellaneous json-quirks 107 // This will check if the json output uses strings or json-booleans to represent bool values 108 log.Info("boolean", "true", true, "false", false) 109 // Handling of duplicate keys. 110 // This is actually ill-handled by the current handler: the format.go 111 // uses a global 'fieldPadding' map and mixes up the two keys. If 'alpha' 112 // is shorter than beta, it sometimes causes erroneous padding -- and what's more 113 // it causes _different_ padding in multi-handler context, e.g. both file- 114 // and console output, making the two mismatch. 115 log.Info("repeated-key 1", "foo", "alpha", "foo", "beta") 116 log.Info("repeated-key 2", "xx", "short", "xx", "longer") 117 } 118 { // loglevels 119 log.Debug("log at level debug") 120 log.Trace("log at level trace") 121 log.Info("log at level info") 122 log.Warn("log at level warn") 123 log.Error("log at level error") 124 } 125 { 126 // The current log formatter has a global map of paddings, storing the 127 // longest seen padding per key in a map. This results in a statefulness 128 // which has some odd side-effects. Demonstrated here: 129 log.Info("test", "bar", "short", "a", "aligned left") 130 log.Info("test", "bar", "a long message", "a", 1) 131 log.Info("test", "bar", "short", "a", "aligned right") 132 } 133 { 134 // This sequence of logs should be output with alignment, so each field becoems a column. 135 log.Info("The following logs should align so that the key-fields make 5 columns") 136 log.Info("Inserted known block", "number", 1_012, "hash", common.HexToHash("0x1234"), "txs", 200, "gas", 1_123_123, "other", "first") 137 log.Info("Inserted new block", "number", 1, "hash", common.HexToHash("0x1235"), "txs", 2, "gas", 1_123, "other", "second") 138 log.Info("Inserted known block", "number", 99, "hash", common.HexToHash("0x12322"), "txs", 10, "gas", 1, "other", "third") 139 log.Warn("Inserted known block", "number", 1_012, "hash", common.HexToHash("0x1234"), "txs", 200, "gas", 99, "other", "fourth") 140 } 141 { // Various types of nil 142 type customStruct struct { 143 A string 144 B *uint64 145 } 146 log.Info("(*big.Int)(nil)", "<nil>", (*big.Int)(nil)) 147 log.Info("(*uint256.Int)(nil)", "<nil>", (*uint256.Int)(nil)) 148 log.Info("(fmt.Stringer)(nil)", "res", (fmt.Stringer)(nil)) 149 log.Info("nil-concrete-stringer", "res", (*time.Time)(nil)) 150 151 log.Info("error(nil) ", "res", error(nil)) 152 log.Info("nil-concrete-error", "res", (*customError)(nil)) 153 154 log.Info("nil-custom-struct", "res", (*customStruct)(nil)) 155 log.Info("raw nil", "res", nil) 156 log.Info("(*uint64)(nil)", "res", (*uint64)(nil)) 157 } 158 { // Logging with 'reserved' keys 159 log.Info("Using keys 't', 'lvl', 'time', 'level' and 'msg'", "t", "t", "time", "time", "lvl", "lvl", "level", "level", "msg", "msg") 160 } 161 { // Logging with wrong attr-value pairs 162 log.Info("Odd pair (1 attr)", "key") 163 log.Info("Odd pair (3 attr)", "key", "value", "key2") 164 } 165 return nil 166 } 167 168 // customError is a type which implements error 169 type customError struct{} 170 171 func (c *customError) Error() string { return "" }