From dd4551bc9e22f84a61e471a00938a665d44a9363 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 2 Mar 2022 11:35:05 +0300 Subject: [PATCH] eth/tracers/logger: use JSON struct tag ",omitempty" to reduce log bloat from blank fields Noticed while debugging Tharsis/EVMOS logs that the logs were extraneous with empty fields such as ```json {"pc":4716,"op":80,"gas":"0x688e5","gasCost":"0x2","memory":"0x","memSize":352,"stack":["0xfa31de01","0x29a","0x7d0","0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd","0x80","0x534","0xc0","0x5f646b5592c4159d4963fbf901f81144ef53cc51a7082435e3a6120a45002ff7","0x15dc","0x34","0x5f646b5592c4159d4963fbf901f81144ef53cc51a7082435e3a6120a45002ff7"],"returnData":"0x","depth":2,"refund":0,"opName":"POP","error":""} {"pc":4717,"op":80,"gas":"0x688e3","gasCost":"0x2","memory":"0x","memSize":352,"stack":["0xfa31de01","0x29a","0x7d0","0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd","0x80","0x534","0xc0","0x5f646b5592c4159d4963fbf901f81144ef53cc51a7082435e3a6120a45002ff7","0x15dc","0x34"],"returnData":"0x","depth":2,"refund":0,"opName":"POP","error":""} ``` with empty fields like "error", "refund", "memory", "returnData". This change adds the JSON tag ",omitempty" to remove the bloat from the above empty fields which shows immediate impact of reducing the logs to ```json {"pc":4716,"op":80,"gas":"0x688e5","gasCost":"0x2","memSize":352,"stack":["0xfa31de01","0x29a","0x7d0","0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd","0x80","0x534","0xc0","0x5f646b5592c4159d4963fbf901f81144ef53cc51a7082435e3a6120a45002ff7","0x15dc","0x34","0x5f646b5592c4159d4963fbf901f81144ef53cc51a7082435e3a6120a45002ff7"],"depth":2,"opName":"POP"} {"pc":4717,"op":80,"gas":"0x688e3","gasCost":"0x2","memSize":352,"stack":["0xfa31de01","0x29a","0x7d0","0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd","0x80","0x534","0xc0","0x5f646b5592c4159d4963fbf901f81144ef53cc51a7082435e3a6120a45002ff7","0x15dc","0x34"],"depth":2,"opName":"POP"} ``` and not only does that reduce the size of logs but it also makes it much easier to quickly debug and grep for errors, which will only be present if erroring. Fixes #24487 --- eth/tracers/logger/gen_structlog.go | 4 ++-- eth/tracers/logger/logger.go | 12 ++++++------ eth/tracers/logger/logger_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/eth/tracers/logger/gen_structlog.go b/eth/tracers/logger/gen_structlog.go index 9e71b555cb63..7ce8cc50d635 100644 --- a/eth/tracers/logger/gen_structlog.go +++ b/eth/tracers/logger/gen_structlog.go @@ -29,8 +29,8 @@ func (s StructLog) MarshalJSON() ([]byte, error) { Depth int `json:"depth"` RefundCounter uint64 `json:"refund"` Err error `json:"-"` - OpName string `json:"opName"` - ErrorString string `json:"error"` + OpName string `json:"opName,omitempty"` + ErrorString string `json:"error,omitempty"` } var enc StructLog enc.Pc = s.Pc diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index 8461935822d8..bbee21e64c57 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -78,12 +78,12 @@ type StructLog struct { // overrides for gencodec type structLogMarshaling struct { - Gas math.HexOrDecimal64 - GasCost math.HexOrDecimal64 - Memory hexutil.Bytes - ReturnData hexutil.Bytes - OpName string `json:"opName"` // adds call to OpName() in MarshalJSON - ErrorString string `json:"error"` // adds call to ErrorString() in MarshalJSON + Gas math.HexOrDecimal64 `json:",omitempty"` + GasCost math.HexOrDecimal64 `json:",omitempty"` + Memory hexutil.Bytes `json:",omitempty"` + ReturnData hexutil.Bytes `json:",omitempty"` + OpName string `json:"opName,omitempty"` // adds call to OpName() in MarshalJSON + ErrorString string `json:"error,omitempty"` // adds call to ErrorString() in MarshalJSON } // OpName formats the operand name in a human-readable format. diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go index 205ee311201a..e44fbff36b5f 100644 --- a/eth/tracers/logger/logger_test.go +++ b/eth/tracers/logger/logger_test.go @@ -17,6 +17,7 @@ package logger import ( + "encoding/json" "math/big" "testing" @@ -72,3 +73,29 @@ func TestStoreCapture(t *testing.T) { t.Errorf("expected %x, got %x", exp, logger.storage[contract.Address()][index]) } } + +// Tests that blank fields don't appear in logs when JSON marshalled, to reduce +// logs bloat and confusion. See https://github.com/ethereum/go-ethereum/issues/24487 +func TestStructLogMarshalingOmitEmpty(t *testing.T) { + tests := []struct { + name string + log *structLogMarshaling + want string + }{ + {"empty err and no fields", &structLogMarshaling{ErrorString: ""}, `{}`}, + {"with Gas cost only", &structLogMarshaling{GasCost: 10}, `{"GasCost":"0xa"}`}, + {"with err", &structLogMarshaling{ErrorString: "this failed"}, `{"error":"this failed"}`}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + blob, err := json.Marshal(tt.log) + if err != nil { + t.Fatal(err) + } + if g, w := string(blob), tt.want; g != w { + t.Fatalf("Mismatched results\n\tGot: %q\n\tWant: %q", g, w) + } + }) + } +}