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) + } + }) + } +}