github.com/number571/tendermint@v0.34.11-gost/libs/log/default.go (about) 1 package log 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "strings" 8 "time" 9 10 "github.com/rs/zerolog" 11 ) 12 13 var _ Logger = (*defaultLogger)(nil) 14 15 type defaultLogger struct { 16 zerolog.Logger 17 18 trace bool 19 } 20 21 // NewDefaultLogger returns a default logger that can be used within Tendermint 22 // and that fulfills the Logger interface. The underlying logging provider is a 23 // zerolog logger that supports typical log levels along with JSON and plain/text 24 // log formats. 25 // 26 // Since zerolog supports typed structured logging and it is difficult to reflect 27 // that in a generic interface, all logging methods accept a series of key/value 28 // pair tuples, where the key must be a string. 29 func NewDefaultLogger(format, level string, trace bool) (Logger, error) { 30 var logWriter io.Writer 31 switch strings.ToLower(format) { 32 case LogFormatPlain, LogFormatText: 33 logWriter = zerolog.ConsoleWriter{ 34 Out: os.Stderr, 35 NoColor: true, 36 TimeFormat: time.RFC3339, 37 FormatLevel: func(i interface{}) string { 38 if ll, ok := i.(string); ok { 39 return strings.ToUpper(ll) 40 } 41 return "????" 42 }, 43 } 44 45 case LogFormatJSON: 46 logWriter = os.Stderr 47 48 default: 49 return nil, fmt.Errorf("unsupported log format: %s", format) 50 } 51 52 logLevel, err := zerolog.ParseLevel(level) 53 if err != nil { 54 return nil, fmt.Errorf("failed to parse log level (%s): %w", level, err) 55 } 56 57 // make the writer thread-safe 58 logWriter = newSyncWriter(logWriter) 59 60 return defaultLogger{ 61 Logger: zerolog.New(logWriter).Level(logLevel).With().Timestamp().Logger(), 62 trace: trace, 63 }, nil 64 } 65 66 // MustNewDefaultLogger delegates a call NewDefaultLogger where it panics on 67 // error. 68 func MustNewDefaultLogger(format, level string, trace bool) Logger { 69 logger, err := NewDefaultLogger(format, level, trace) 70 if err != nil { 71 panic(err) 72 } 73 74 return logger 75 } 76 77 func (l defaultLogger) Info(msg string, keyVals ...interface{}) { 78 l.Logger.Info().Fields(getLogFields(keyVals...)).Msg(msg) 79 } 80 81 func (l defaultLogger) Error(msg string, keyVals ...interface{}) { 82 e := l.Logger.Error() 83 if l.trace { 84 e = e.Stack() 85 } 86 87 e.Fields(getLogFields(keyVals...)).Msg(msg) 88 } 89 90 func (l defaultLogger) Debug(msg string, keyVals ...interface{}) { 91 l.Logger.Debug().Fields(getLogFields(keyVals...)).Msg(msg) 92 } 93 94 func (l defaultLogger) With(keyVals ...interface{}) Logger { 95 return defaultLogger{ 96 Logger: l.Logger.With().Fields(getLogFields(keyVals...)).Logger(), 97 trace: l.trace, 98 } 99 } 100 101 func getLogFields(keyVals ...interface{}) map[string]interface{} { 102 if len(keyVals)%2 != 0 { 103 return nil 104 } 105 106 fields := make(map[string]interface{}, len(keyVals)) 107 for i := 0; i < len(keyVals); i += 2 { 108 fields[fmt.Sprint(keyVals[i])] = keyVals[i+1] 109 } 110 111 return fields 112 }