github.com/klaytn/klaytn@v1.12.1/log/zap_logger.go (about) 1 // Copyright 2018 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package log 18 19 import ( 20 "errors" 21 "fmt" 22 "sync" 23 24 "go.uber.org/zap" 25 "go.uber.org/zap/zapcore" 26 ) 27 28 var zlManager = zapLoggerManager{ 29 "stderr", // Use stderr to outputPath instead of stdout to be aligned with log15. 30 "json", zapcore.InfoLevel, 31 sync.Mutex{}, 32 make(map[ModuleID][]*zapLogger), 33 } 34 35 type zapLoggerManager struct { 36 outputPath string 37 encodingType string 38 logLevel zapcore.Level 39 mutex sync.Mutex 40 loggersMap map[ModuleID][]*zapLogger 41 } 42 43 type zapLogger struct { 44 mi ModuleID 45 cfg *zap.Config 46 sl *zap.SugaredLogger 47 } 48 49 // A zapLogger generated from NewWith inherits InitialFields and ModuleID from its parent. 50 func (zl *zapLogger) NewWith(keysAndValues ...interface{}) Logger { 51 zlManager.mutex.Lock() 52 defer zlManager.mutex.Unlock() 53 54 newCfg := genDefaultConfig() 55 for k, v := range zl.cfg.InitialFields { 56 newCfg.InitialFields[k] = v 57 } 58 newCfg.Level.SetLevel(zl.cfg.Level.Level()) 59 return genLoggerZap(zl.mi, newCfg) 60 } 61 62 func (zl *zapLogger) newModuleLogger(mi ModuleID) Logger { 63 zlManager.mutex.Lock() 64 defer zlManager.mutex.Unlock() 65 66 zapCfg := genDefaultConfig() 67 zapCfg.InitialFields[module] = mi 68 return genLoggerZap(mi, zapCfg) 69 } 70 71 func (zl *zapLogger) Trace(msg string, keysAndValues ...interface{}) { 72 zl.sl.Debugw(msg, keysAndValues...) 73 } 74 75 func (zl *zapLogger) Debug(msg string, keysAndValues ...interface{}) { 76 zl.sl.Debugw(msg, keysAndValues...) 77 } 78 79 func (zl *zapLogger) Info(msg string, keysAndValues ...interface{}) { 80 zl.sl.Infow(msg, keysAndValues...) 81 } 82 83 func (zl *zapLogger) Warn(msg string, keysAndValues ...interface{}) { 84 zl.sl.Warnw(msg, keysAndValues...) 85 } 86 87 func (zl *zapLogger) Error(msg string, keysAndValues ...interface{}) { 88 zl.sl.Errorw(msg, keysAndValues...) 89 } 90 91 func (zl *zapLogger) ErrorWithStack(msg string, keysAndValues ...interface{}) { 92 zl.sl.Errorw(msg, keysAndValues...) 93 } 94 95 func (zl *zapLogger) Crit(msg string, keysAndValues ...interface{}) { 96 zl.sl.Fatalw(msg, keysAndValues...) 97 } 98 99 func (zl *zapLogger) CritWithStack(msg string, keysAndValues ...interface{}) { 100 zl.sl.Fatalw(msg, keysAndValues...) 101 } 102 103 // GetHandler and SetHandler do nothing but exist to make consistency in Logger interface. 104 func (zl *zapLogger) GetHandler() Handler { 105 return nil 106 } 107 108 func (zl *zapLogger) SetHandler(h Handler) { 109 } 110 111 func (zl *zapLogger) setLevel(lvl Lvl) { 112 zl.cfg.Level.SetLevel(lvlToZapLevel(lvl)) 113 } 114 115 // register registers the receiver to zapLoggerManager. 116 func (zl *zapLogger) register() { 117 zlManager.loggersMap[zl.mi] = append(zlManager.loggersMap[zl.mi], zl) 118 } 119 120 func genBaseLoggerZap() Logger { 121 return genLoggerZap(BaseLogger, genDefaultConfig()) 122 } 123 124 // genLoggerZap creates a zapLogger with given ModuleID and Config. 125 func genLoggerZap(mi ModuleID, cfg *zap.Config) Logger { 126 logger, err := cfg.Build() 127 if err != nil { 128 Fatalf("Error while building zapLogger from the config. ModuleID: %v, err: %v", mi, err) 129 } 130 newLogger := &zapLogger{mi, cfg, logger.Sugar()} 131 newLogger.register() 132 return newLogger 133 } 134 135 // ChangeLogLevelWithName changes the log level of loggers with given ModuleName. 136 func ChangeLogLevelWithName(moduleName string, lvl Lvl) error { 137 if err := levelCheck(lvl); err != nil { 138 return err 139 } 140 mi := GetModuleID(moduleName) 141 if mi == ModuleNameLen { 142 return errors.New("entered module name does not match with any existing log module") 143 } 144 return ChangeLogLevelWithID(mi, lvl) 145 } 146 147 // ChangeLogLevelWithName changes the log level of loggers with given ModuleID. 148 func ChangeLogLevelWithID(mi ModuleID, lvl Lvl) error { 149 if err := levelCheck(lvl); err != nil { 150 return err 151 } 152 if err := idCheck(mi); err != nil { 153 return err 154 } 155 loggers := zlManager.loggersMap[mi] 156 for _, logger := range loggers { 157 logger.setLevel(lvl) 158 } 159 return nil 160 } 161 162 func ChangeGlobalLogLevel(glogger *GlogHandler, lvl Lvl) error { 163 if err := levelCheck(lvl); err != nil { 164 return err 165 } 166 for _, loggers := range zlManager.loggersMap { 167 for _, logger := range loggers { 168 logger.setLevel(lvl) 169 } 170 } 171 172 if glogger != nil { 173 glogger.Verbosity(lvl) 174 } 175 return nil 176 } 177 178 func levelCheck(lvl Lvl) error { 179 if lvl >= LvlEnd { 180 return errors.New(fmt.Sprintf("insert log level less than %d", LvlEnd)) 181 } 182 if lvl < LvlCrit { 183 return errors.New(fmt.Sprintf("insert log level greater than or equal to %d", LvlCrit)) 184 } 185 return nil 186 } 187 188 func idCheck(mi ModuleID) error { 189 if mi >= ModuleNameLen { 190 return errors.New(fmt.Sprintf("insert log level less than %d", ModuleNameLen)) 191 } 192 if mi <= BaseLogger { 193 return errors.New(fmt.Sprintf("insert log level greater than %d", BaseLogger)) 194 } 195 return nil 196 } 197 198 func lvlToZapLevel(lvl Lvl) zapcore.Level { 199 switch lvl { 200 case LvlCrit: 201 return zapcore.FatalLevel 202 case LvlError: 203 return zapcore.ErrorLevel 204 case LvlWarn: 205 return zapcore.WarnLevel 206 case LvlInfo: 207 return zapcore.InfoLevel 208 case LvlDebug: 209 return zapcore.DebugLevel 210 case LvlTrace: 211 return zapcore.DebugLevel 212 default: 213 baseLogger.Error("Unexpected log level entered. Use InfoLevel instead.", "entered level", lvl) 214 return zapcore.InfoLevel 215 } 216 } 217 218 func genDefaultEncoderConfig() zapcore.EncoderConfig { 219 return zapcore.EncoderConfig{ 220 TimeKey: "ts", 221 LevelKey: "level", 222 NameKey: "logger", 223 // CallerKey: "caller", 224 MessageKey: "msg", 225 StacktraceKey: "stacktrace", 226 LineEnding: zapcore.DefaultLineEnding, 227 EncodeLevel: zapcore.LowercaseLevelEncoder, 228 EncodeTime: zapcore.ISO8601TimeEncoder, 229 EncodeDuration: zapcore.SecondsDurationEncoder, 230 // EncodeCaller: zapcore.ShortCallerEncoder, 231 } 232 } 233 234 func genDefaultConfig() *zap.Config { 235 encoderConfig := genDefaultEncoderConfig() 236 return &zap.Config{ 237 Encoding: zlManager.encodingType, 238 Level: zap.NewAtomicLevelAt(zlManager.logLevel), 239 OutputPaths: []string{zlManager.outputPath}, 240 Development: false, 241 EncoderConfig: encoderConfig, 242 InitialFields: make(map[string]interface{}), 243 } 244 }