Skip to content

Commit aedfea6

Browse files
committed
all: make logs a bit easier on the eye to digest (ethereum#22665)
1 parent 3d21631 commit aedfea6

File tree

8 files changed

+193
-19
lines changed

8 files changed

+193
-19
lines changed

accounts/url.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (u URL) String() string {
6464
func (u URL) TerminalString() string {
6565
url := u.String()
6666
if len(url) > 32 {
67-
return url[:31] + ""
67+
return url[:31] + ".."
6868
}
6969
return url
7070
}
@@ -76,10 +76,9 @@ func (u URL) MarshalJSON() ([]byte, error) {
7676

7777
// Cmp compares x and y and returns:
7878
//
79-
// -1 if x < y
80-
// 0 if x == y
81-
// +1 if x > y
82-
//
79+
// -1 if x < y
80+
// 0 if x == y
81+
// +1 if x > y
8382
func (u URL) Cmp(url URL) int {
8483
if u.Scheme == url.Scheme {
8584
return strings.Compare(u.Path, url.Path)

common/types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (h Hash) Cmp(other Hash) int {
107107
func (h Hash) IsZero() bool { return h == Hash{} }
108108

109109
// Get the string representation of the underlying hash
110-
func (h Hash) Str() string { return string(h[:]) }
110+
func (h Hash) Str() string { return string(h[:]) }
111111

112112
// Bytes gets the byte representation of the underlying hash.
113113
func (h Hash) Bytes() []byte { return h[:] }
@@ -116,12 +116,12 @@ func (h Hash) Bytes() []byte { return h[:] }
116116
func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) }
117117

118118
// Hex converts a hash to a hex string.
119-
func (h Hash) Hex() string { return hexutil.Encode(h[:]) }
119+
func (h Hash) Hex() string { return hexutil.Encode(h[:]) }
120120

121121
// TerminalString implements log.TerminalStringer, formatting a string for console
122122
// output during logging.
123123
func (h Hash) TerminalString() string {
124-
return fmt.Sprintf("%x%x", h[:3], h[29:])
124+
return fmt.Sprintf("%x..%x", h[:3], h[29:])
125125
}
126126

127127
// String implements the stringer interface and is used also by the logger when

core/blockchain.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
440440
// Make sure that both the block as well at its state trie exists
441441
block := bc.GetBlockByHash(hash)
442442
if block == nil {
443-
return fmt.Errorf("non existent block [%x]", hash[:4])
443+
return fmt.Errorf("non existent block [%x..]", hash[:4])
444444
}
445445
if _, err := trie.NewSecure(block.Root(), bc.stateCache.TrieDB()); err != nil {
446446
return err
@@ -1055,7 +1055,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
10551055
if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() {
10561056
log.Error("Non contiguous receipt insert", "number", blockChain[i].Number(), "hash", blockChain[i].Hash(), "parent", blockChain[i].ParentHash(),
10571057
"prevnumber", blockChain[i-1].Number(), "prevhash", blockChain[i-1].Hash())
1058-
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x], item %d is #%d [%x] (parent [%x])", i-1, blockChain[i-1].NumberU64(),
1058+
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, blockChain[i-1].NumberU64(),
10591059
blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4])
10601060
}
10611061
}
@@ -1075,7 +1075,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
10751075
blockHash, blockNumber := block.Hash(), block.NumberU64()
10761076
// Short circuit if the owner header is unknown
10771077
if !bc.HasHeader(blockHash, blockNumber) {
1078-
return i, fmt.Errorf("containing header #%d [%x] unknown", blockNumber, blockHash.Bytes()[:4])
1078+
return i, fmt.Errorf("containing header #%d [%x..] unknown", blockNumber, blockHash.Bytes()[:4])
10791079
}
10801080
// Skip if the entire data is already known
10811081
if bc.HasBlock(blockHash, blockNumber) {
@@ -1422,7 +1422,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
14221422
log.Error("Non contiguous block insert", "number", chain[i].Number(), "hash", chain[i].Hash(),
14231423
"parent", chain[i].ParentHash(), "prevnumber", chain[i-1].Number(), "prevhash", chain[i-1].Hash())
14241424

1425-
return 0, nil, nil, fmt.Errorf("non contiguous insert: item %d is #%d [%x], item %d is #%d [%x] (parent [%x])", i-1, chain[i-1].NumberU64(),
1425+
return 0, nil, nil, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, chain[i-1].NumberU64(),
14261426
chain[i-1].Hash().Bytes()[:4], i, chain[i].NumberU64(), chain[i].Hash().Bytes()[:4], chain[i].ParentHash().Bytes()[:4])
14271427
}
14281428
}

core/blockchain_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,13 +1221,13 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
12211221
t.Fatalf("block %d: failed to insert into chain: %v", i, err)
12221222
}
12231223
if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() {
1224-
t.Errorf("block %d: current block/header mismatch: block #%d [%x], header #%d [%x]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4])
1224+
t.Errorf("block %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4])
12251225
}
12261226
if _, err := chain.InsertChain(forks[i : i+1]); err != nil {
12271227
t.Fatalf(" fork %d: failed to insert into chain: %v", i, err)
12281228
}
12291229
if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() {
1230-
t.Errorf(" fork %d: current block/header mismatch: block #%d [%x], header #%d [%x]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4])
1230+
t.Errorf(" fork %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4])
12311231
}
12321232
}
12331233
}

core/chain_indexer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ func (c *ChainIndexer) processSection(section uint64, lastHead common.Hash) (com
356356
}
357357
header := GetHeader(c.chainDb, hash, number)
358358
if header == nil {
359-
return common.Hash{}, fmt.Errorf("block #%d [%x] not found", number, hash[:4])
359+
return common.Hash{}, fmt.Errorf("block #%d [%x..] not found", number, hash[:4])
360360
} else if header.ParentHash != lastHead {
361361
return common.Hash{}, errors.New("chain reorged during section processing")
362362
}

core/headerchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)
205205
log.Error("Non contiguous header insert", "number", chain[i].Number, "hash", chain[i].Hash(),
206206
"parent", chain[i].ParentHash, "prevnumber", chain[i-1].Number, "prevhash", chain[i-1].Hash())
207207

208-
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x], item %d is #%d [%x] (parent [%x])", i-1, chain[i-1].Number,
208+
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, chain[i-1].Number,
209209
chain[i-1].Hash().Bytes()[:4], i, chain[i].Number, chain[i].Hash().Bytes()[:4], chain[i].ParentHash[:4])
210210
}
211211
}

log/format.go

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"encoding/json"
66
"fmt"
7+
"math/big"
78
"reflect"
89
"strconv"
910
"strings"
@@ -327,11 +328,20 @@ func formatLogfmtValue(value interface{}, term bool) string {
327328
return "nil"
328329
}
329330

330-
if t, ok := value.(time.Time); ok {
331+
switch v := value.(type) {
332+
case time.Time:
331333
// Performance optimization: No need for escaping since the provided
332334
// timeFormat doesn't have any escape characters, and escaping is
333335
// expensive.
334-
return t.Format(timeFormat)
336+
return v.Format(timeFormat)
337+
338+
case *big.Int:
339+
// Big ints get consumed by the Stringer clause so we need to handle
340+
// them earlier on.
341+
if v == nil {
342+
return "<nil>"
343+
}
344+
return formatLogfmtBigInt(v)
335345
}
336346
if term {
337347
if s, ok := value.(TerminalStringer); ok {
@@ -347,15 +357,105 @@ func formatLogfmtValue(value interface{}, term bool) string {
347357
return strconv.FormatFloat(float64(v), floatFormat, 3, 64)
348358
case float64:
349359
return strconv.FormatFloat(v, floatFormat, 3, 64)
350-
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
360+
case int8, uint8:
351361
return fmt.Sprintf("%d", value)
362+
case int:
363+
return FormatLogfmtInt64(int64(v))
364+
case int16:
365+
return FormatLogfmtInt64(int64(v))
366+
case int32:
367+
return FormatLogfmtInt64(int64(v))
368+
case int64:
369+
return FormatLogfmtInt64(v)
370+
case uint:
371+
return FormatLogfmtUint64(uint64(v))
372+
case uint16:
373+
return FormatLogfmtUint64(uint64(v))
374+
case uint32:
375+
return FormatLogfmtUint64(uint64(v))
376+
case uint64:
377+
return FormatLogfmtUint64(v)
352378
case string:
353379
return escapeString(v)
354380
default:
355381
return escapeString(fmt.Sprintf("%+v", value))
356382
}
357383
}
358384

385+
// FormatLogfmtInt64 formats a potentially big number in a friendlier split format.
386+
func FormatLogfmtInt64(n int64) string {
387+
if n < 0 {
388+
return formatLogfmtUint64(uint64(-n), true)
389+
}
390+
return formatLogfmtUint64(uint64(n), false)
391+
}
392+
393+
// FormatLogfmtUint64 formats a potentially big number in a friendlier split format.
394+
func FormatLogfmtUint64(n uint64) string {
395+
return formatLogfmtUint64(n, false)
396+
}
397+
398+
func formatLogfmtUint64(n uint64, neg bool) string {
399+
// Small numbers are fine as is
400+
if n < 100000 {
401+
if neg {
402+
return strconv.Itoa(-int(n))
403+
} else {
404+
return strconv.Itoa(int(n))
405+
}
406+
}
407+
// Large numbers should be split
408+
const maxLength = 26
409+
410+
var (
411+
out = make([]byte, maxLength)
412+
i = maxLength - 1
413+
comma = 0
414+
)
415+
for ; n > 0; i-- {
416+
if comma == 3 {
417+
comma = 0
418+
out[i] = ','
419+
} else {
420+
comma++
421+
out[i] = '0' + byte(n%10)
422+
n /= 10
423+
}
424+
}
425+
if neg {
426+
out[i] = '-'
427+
i--
428+
}
429+
return string(out[i+1:])
430+
}
431+
432+
var big1000 = big.NewInt(1000)
433+
434+
// formatLogfmtBigInt formats a potentially gigantic number in a friendlier split
435+
// format.
436+
func formatLogfmtBigInt(n *big.Int) string {
437+
// Most number don't need fancy handling, just downcast
438+
if n.IsUint64() {
439+
return FormatLogfmtUint64(n.Uint64())
440+
}
441+
if n.IsInt64() {
442+
return FormatLogfmtInt64(n.Int64())
443+
}
444+
// Ok, huge number needs huge effort
445+
groups := make([]string, 0, 8) // random initial size to cover most cases
446+
for n.Cmp(big1000) >= 0 {
447+
_, mod := n.DivMod(n, big1000, nil)
448+
groups = append(groups, fmt.Sprintf("%03d", mod))
449+
}
450+
groups = append(groups, n.String())
451+
452+
last := len(groups) - 1
453+
for i := 0; i < len(groups)/2; i++ {
454+
groups[i], groups[last-i] = groups[last-i], groups[i]
455+
}
456+
return strings.Join(groups, ",")
457+
}
458+
359459
// escapeString checks if the provided string needs escaping/quoting, and
360460
// calls strconv.Quote if needed
361461
func escapeString(s string) string {

log/format_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package log
2+
3+
import (
4+
"math"
5+
"math/rand"
6+
"testing"
7+
)
8+
9+
func TestPrettyInt64(t *testing.T) {
10+
tests := []struct {
11+
n int64
12+
s string
13+
}{
14+
{0, "0"},
15+
{10, "10"},
16+
{-10, "-10"},
17+
{100, "100"},
18+
{-100, "-100"},
19+
{1000, "1000"},
20+
{-1000, "-1000"},
21+
{10000, "10000"},
22+
{-10000, "-10000"},
23+
{99999, "99999"},
24+
{-99999, "-99999"},
25+
{100000, "100,000"},
26+
{-100000, "-100,000"},
27+
{1000000, "1,000,000"},
28+
{-1000000, "-1,000,000"},
29+
{math.MaxInt64, "9,223,372,036,854,775,807"},
30+
{math.MinInt64, "-9,223,372,036,854,775,808"},
31+
}
32+
for i, tt := range tests {
33+
if have := FormatLogfmtInt64(tt.n); have != tt.s {
34+
t.Errorf("test %d: format mismatch: have %s, want %s", i, have, tt.s)
35+
}
36+
}
37+
}
38+
39+
func TestPrettyUint64(t *testing.T) {
40+
tests := []struct {
41+
n uint64
42+
s string
43+
}{
44+
{0, "0"},
45+
{10, "10"},
46+
{100, "100"},
47+
{1000, "1000"},
48+
{10000, "10000"},
49+
{99999, "99999"},
50+
{100000, "100,000"},
51+
{1000000, "1,000,000"},
52+
{math.MaxUint64, "18,446,744,073,709,551,615"},
53+
}
54+
for i, tt := range tests {
55+
if have := FormatLogfmtUint64(tt.n); have != tt.s {
56+
t.Errorf("test %d: format mismatch: have %s, want %s", i, have, tt.s)
57+
}
58+
}
59+
}
60+
61+
var sink string
62+
63+
func BenchmarkPrettyInt64Logfmt(b *testing.B) {
64+
b.ReportAllocs()
65+
for i := 0; i < b.N; i++ {
66+
sink = FormatLogfmtInt64(rand.Int63())
67+
}
68+
}
69+
70+
func BenchmarkPrettyUint64Logfmt(b *testing.B) {
71+
b.ReportAllocs()
72+
for i := 0; i < b.N; i++ {
73+
sink = FormatLogfmtUint64(rand.Uint64())
74+
}
75+
}

0 commit comments

Comments
 (0)