|
4 | 4 | package evm |
5 | 5 |
|
6 | 6 | import ( |
| 7 | + "encoding/json" |
7 | 8 | "fmt" |
8 | 9 | "io" |
| 10 | + "reflect" |
| 11 | + "time" |
9 | 12 |
|
10 | 13 | "github.com/ethereum/go-ethereum/log" |
11 | 14 | ) |
12 | 15 |
|
| 16 | +const ( |
| 17 | + errorKey = "LOG15_ERROR" |
| 18 | + timeFormat = "2006-01-02T15:04:05-0700" |
| 19 | +) |
| 20 | + |
13 | 21 | type SubnetEVMLogger struct { |
14 | 22 | log.Handler |
15 | 23 | } |
@@ -56,12 +64,56 @@ func SubnetEVMTermFormat(alias string) log.Format { |
56 | 64 | func SubnetEVMJSONFormat(alias string) log.Format { |
57 | 65 | prefix := fmt.Sprintf("%s Chain", alias) |
58 | 66 | return log.FormatFunc(func(r *log.Record) []byte { |
59 | | - location := fmt.Sprintf("%+v", r.Call) |
60 | | - r.KeyNames.Lvl = "level" |
61 | | - r.KeyNames.Time = "timestamp" |
62 | | - r.Ctx = append(r.Ctx, "logger", prefix) |
63 | | - r.Ctx = append(r.Ctx, "caller", location) |
| 67 | + props := make(map[string]interface{}, 5+len(r.Ctx)/2) |
| 68 | + props["timestamp"] = r.Time |
| 69 | + props["level"] = r.Lvl.String() |
| 70 | + props[r.KeyNames.Msg] = r.Msg |
| 71 | + props["logger"] = prefix |
| 72 | + props["caller"] = fmt.Sprintf("%+v", r.Call) |
| 73 | + for i := 0; i < len(r.Ctx); i += 2 { |
| 74 | + k, ok := r.Ctx[i].(string) |
| 75 | + if !ok { |
| 76 | + props[errorKey] = fmt.Sprintf("%+v is not a string key", r.Ctx[i]) |
| 77 | + } else { |
| 78 | + props[k] = formatJSONValue(r.Ctx[i+1]) |
| 79 | + } |
| 80 | + } |
64 | 81 |
|
65 | | - return log.JSONFormat().Format(r) |
| 82 | + b, err := json.Marshal(props) |
| 83 | + if err != nil { |
| 84 | + b, _ = json.Marshal(map[string]string{ |
| 85 | + errorKey: err.Error(), |
| 86 | + }) |
| 87 | + return b |
| 88 | + } |
| 89 | + |
| 90 | + b = append(b, '\n') |
| 91 | + return b |
66 | 92 | }) |
67 | 93 | } |
| 94 | + |
| 95 | +func formatJSONValue(value interface{}) (result interface{}) { |
| 96 | + defer func() { |
| 97 | + if err := recover(); err != nil { |
| 98 | + if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr && v.IsNil() { |
| 99 | + result = "nil" |
| 100 | + } else { |
| 101 | + panic(err) |
| 102 | + } |
| 103 | + } |
| 104 | + }() |
| 105 | + |
| 106 | + switch v := value.(type) { |
| 107 | + case time.Time: |
| 108 | + return v.Format(timeFormat) |
| 109 | + |
| 110 | + case error: |
| 111 | + return v.Error() |
| 112 | + |
| 113 | + case fmt.Stringer: |
| 114 | + return v.String() |
| 115 | + |
| 116 | + default: |
| 117 | + return v |
| 118 | + } |
| 119 | +} |
0 commit comments