github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/libs/log/zerolog_logger.go (about) 1 package log 2 3 import ( 4 "fmt" 5 "io" 6 7 "github.com/rs/zerolog" 8 "gopkg.in/natefinch/lumberjack.v2" 9 ) 10 11 var _ Logger = (*ZeroLogWrapper)(nil) 12 13 // ZeroLogWrapper provides a wrapper around a zerolog.Logger instance. It implements 14 // Tendermint's Logger interface. 15 type ZeroLogWrapper struct { 16 zerolog.Logger 17 } 18 19 type ZeroLogConfig struct { 20 IsLogPlain bool 21 LogLevel string 22 23 LogPath string 24 LogMaxAge int 25 LogMaxSize int 26 LogMaxBackups int 27 } 28 29 func NewZeroLogConfig(isLogPlain bool, logLevel string, logPath string, logMaxAge int, logMaxSize int, logMaxBackups int) ZeroLogConfig { 30 return ZeroLogConfig{ 31 IsLogPlain: isLogPlain, 32 LogLevel: logLevel, 33 LogPath: logPath, 34 LogMaxAge: logMaxAge, 35 LogMaxSize: logMaxSize, 36 LogMaxBackups: logMaxBackups, 37 } 38 } 39 40 func NewZeroLogLogger(cfg ZeroLogConfig, consoleWriter io.Writer) (Logger, error) { 41 var logWriter io.Writer 42 if cfg.IsLogPlain { 43 logWriter = zerolog.ConsoleWriter{ 44 Out: consoleWriter, 45 TimeFormat: "2006/01/02-15:04:05.999", 46 } 47 } else { 48 logWriter = consoleWriter 49 } 50 51 var zeroLogLogger zerolog.Logger 52 if cfg.LogPath != "" { 53 // initialize the rotator 54 rotator := &lumberjack.Logger{ 55 Filename: cfg.LogPath, 56 MaxAge: cfg.LogMaxAge, 57 MaxSize: cfg.LogMaxSize, 58 MaxBackups: cfg.LogMaxBackups, 59 } 60 61 // set log format 62 var fileLogWriter io.Writer 63 if cfg.IsLogPlain { 64 fileLogWriter = zerolog.ConsoleWriter{ 65 Out: rotator, 66 NoColor: true, 67 TimeFormat: "2006/01/02-15:04:05.999", 68 } 69 } else { 70 fileLogWriter = rotator 71 } 72 73 zeroLogLogger = zerolog.New(zerolog.MultiLevelWriter(logWriter, fileLogWriter)).With().Timestamp().Logger() 74 } else { 75 zeroLogLogger = zerolog.New(logWriter).With().Timestamp().Logger() 76 } 77 78 leveledZeroLogLogger, err := ParseLogLevel(cfg.LogLevel, ZeroLogWrapper{zeroLogLogger}, "info") 79 if err != nil { 80 return nil, fmt.Errorf("failed to parse log level (%s): %w", cfg.LogLevel, err) 81 } 82 83 return leveledZeroLogLogger, nil 84 } 85 86 func init() { 87 zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs 88 } 89 90 // Info implements Tendermint's Logger interface and logs with level INFO. A set 91 // of key/value tuples may be provided to add context to the log. The number of 92 // tuples must be even and the key of the tuple must be a string. 93 func (z ZeroLogWrapper) Info(msg string, keyVals ...interface{}) { 94 z.Logger.Info().Fields(getLogFields(keyVals...)).Msg(msg) 95 } 96 97 // Error implements Tendermint's Logger interface and logs with level ERR. A set 98 // of key/value tuples may be provided to add context to the log. The number of 99 // tuples must be even and the key of the tuple must be a string. 100 func (z ZeroLogWrapper) Error(msg string, keyVals ...interface{}) { 101 z.Logger.Error().Fields(getLogFields(keyVals...)).Msg(msg) 102 } 103 104 // Debug implements Tendermint's Logger interface and logs with level DEBUG. A set 105 // of key/value tuples may be provided to add context to the log. The number of 106 // tuples must be even and the key of the tuple must be a string. 107 func (z ZeroLogWrapper) Debug(msg string, keyVals ...interface{}) { 108 z.Logger.Debug().Fields(getLogFields(keyVals...)).Msg(msg) 109 } 110 111 // With returns a new wrapped logger with additional context provided by a set 112 // of key/value tuples. The number of tuples must be even and the key of the 113 // tuple must be a string. 114 func (z ZeroLogWrapper) With(keyVals ...interface{}) Logger { 115 return ZeroLogWrapper{z.Logger.With().Fields(getLogFields(keyVals...)).Logger()} 116 } 117 118 func getLogFields(keyVals ...interface{}) map[string]interface{} { 119 if len(keyVals)%2 != 0 { 120 return nil 121 } 122 123 fields := make(map[string]interface{}) 124 for i := 0; i < len(keyVals); i += 2 { 125 fields[keyVals[i].(string)] = keyVals[i+1] 126 } 127 128 return fields 129 }