github.com/status-im/status-go@v1.1.0/logutils/zap_adapter.go (about) 1 package logutils 2 3 import ( 4 "fmt" 5 "math" 6 "time" 7 8 "go.uber.org/zap" 9 "go.uber.org/zap/zapcore" 10 11 "github.com/ethereum/go-ethereum/log" 12 13 "github.com/status-im/status-go/protocol/zaputil" 14 ) 15 16 type gethLoggerCore struct { 17 zapcore.LevelEnabler 18 fields []zapcore.Field 19 logger log.Logger 20 } 21 22 func (c gethLoggerCore) With(fields []zapcore.Field) zapcore.Core { 23 clone := c.clone() 24 clone.fields = append(clone.fields, fields...) 25 return clone 26 } 27 28 func (c gethLoggerCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry { 29 if c.Enabled(ent.Level) { 30 return ce.AddCore(ent, c) 31 } 32 return ce 33 } 34 func (c gethLoggerCore) Write(ent zapcore.Entry, fields []zapcore.Field) error { 35 fields = append(c.fields[:], fields...) 36 37 var args []interface{} 38 for _, f := range fields { 39 switch f.Type { 40 case zapcore.ArrayMarshalerType, 41 zapcore.ObjectMarshalerType, 42 zapcore.BinaryType, 43 zapcore.ByteStringType, 44 zapcore.Complex128Type, 45 zapcore.ReflectType, 46 zapcore.StringerType, 47 zapcore.ErrorType: 48 args = append(args, f.Key, f.Interface) 49 case zapcore.BoolType: 50 args = append(args, f.Key, f.Integer == 1) 51 case zapcore.DurationType: 52 args = append(args, f.Key, time.Duration(f.Integer)) 53 case zapcore.Float64Type: 54 args = append(args, f.Key, math.Float64frombits(uint64(f.Integer))) 55 case zapcore.Float32Type: 56 args = append(args, f.Key, math.Float32frombits(uint32(f.Integer))) 57 case zapcore.Int64Type, 58 zapcore.Int32Type, 59 zapcore.Int16Type, 60 zapcore.Int8Type, 61 zapcore.Uint64Type, 62 zapcore.Uint32Type, 63 zapcore.Uint16Type, 64 zapcore.Uint8Type: 65 args = append(args, f.Key, f.Integer) 66 case zapcore.UintptrType: 67 args = append(args, f.Key, uintptr(f.Integer)) 68 case zapcore.StringType: 69 args = append(args, f.Key, f.String) 70 case zapcore.TimeType: 71 if f.Interface != nil { 72 args = append(args, f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location))) 73 } else { 74 // Fall back to UTC if location is nil. 75 args = append(args, f.Key, time.Unix(0, f.Integer)) 76 } 77 case zapcore.NamespaceType: 78 args = append(args, "namespace", f.Key) 79 case zapcore.SkipType: 80 break 81 default: 82 panic(fmt.Sprintf("unknown field type: %v", f)) 83 } 84 } 85 86 // set callDepth to 3 for `Output` to skip the calls to zap.Logger 87 // and get the correct caller in the log 88 callDepth := 3 89 switch ent.Level { 90 case zapcore.DebugLevel: 91 c.logger.Output(ent.Message, log.LvlDebug, callDepth, args...) 92 case zapcore.InfoLevel: 93 c.logger.Output(ent.Message, log.LvlInfo, callDepth, args...) 94 case zapcore.WarnLevel: 95 c.logger.Output(ent.Message, log.LvlWarn, callDepth, args...) 96 case zapcore.ErrorLevel: 97 c.logger.Output(ent.Message, log.LvlError, callDepth, args...) 98 case zapcore.DPanicLevel, zapcore.PanicLevel, zapcore.FatalLevel: 99 c.logger.Output(ent.Message, log.LvlCrit, callDepth, args...) 100 } 101 102 return nil 103 } 104 105 func (gethLoggerCore) Sync() error { 106 return nil 107 } 108 109 func (c *gethLoggerCore) clone() *gethLoggerCore { 110 return &gethLoggerCore{ 111 LevelEnabler: c.LevelEnabler, 112 fields: c.fields, 113 logger: c.logger, 114 } 115 } 116 117 // NewZapAdapter returns a new zapcore.Core interface which forwards logs to log.Logger. 118 func NewZapAdapter(logger log.Logger, enab zapcore.LevelEnabler) zapcore.Core { 119 return &gethLoggerCore{ 120 LevelEnabler: enab, 121 logger: logger, 122 } 123 } 124 125 // NewZapLoggerWithAdapter returns a logger forwarding all logs with level info and above. 126 func NewZapLoggerWithAdapter(logger log.Logger) (*zap.Logger, error) { 127 if err := zaputil.RegisterJSONHexEncoder(); err != nil { 128 panic(err) 129 } 130 131 cfg := zap.Config{ 132 Level: zap.NewAtomicLevelAt(zapcore.DebugLevel), 133 Development: false, 134 Sampling: nil, 135 Encoding: "json-hex", 136 EncoderConfig: zap.NewProductionEncoderConfig(), 137 OutputPaths: []string{"stderr"}, 138 ErrorOutputPaths: []string{"stderr"}, 139 } 140 adapter := zap.WrapCore( 141 func(zapcore.Core) zapcore.Core { 142 return NewZapAdapter(logger, cfg.Level) 143 }, 144 ) 145 log.PrintOrigins(true) 146 return cfg.Build(adapter) 147 }