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 "" }