github.com/RajatVaryani/mattermost-server@v5.11.1+incompatible/mlog/log.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package mlog 5 6 import ( 7 "io" 8 "log" 9 "os" 10 11 "go.uber.org/zap" 12 "go.uber.org/zap/zapcore" 13 "gopkg.in/natefinch/lumberjack.v2" 14 ) 15 16 const ( 17 // Very verbose messages for debugging specific issues 18 LevelDebug = "debug" 19 // Default log level, informational 20 LevelInfo = "info" 21 // Warnings are messages about possible issues 22 LevelWarn = "warn" 23 // Errors are messages about things we know are problems 24 LevelError = "error" 25 ) 26 27 // Type and function aliases from zap to limit the libraries scope into MM code 28 type Field = zapcore.Field 29 30 var Int64 = zap.Int64 31 var Int = zap.Int 32 var Uint32 = zap.Uint32 33 var String = zap.String 34 var Any = zap.Any 35 var Err = zap.Error 36 var Bool = zap.Bool 37 38 type LoggerConfiguration struct { 39 EnableConsole bool 40 ConsoleJson bool 41 ConsoleLevel string 42 EnableFile bool 43 FileJson bool 44 FileLevel string 45 FileLocation string 46 } 47 48 type Logger struct { 49 zap *zap.Logger 50 consoleLevel zap.AtomicLevel 51 fileLevel zap.AtomicLevel 52 } 53 54 func getZapLevel(level string) zapcore.Level { 55 switch level { 56 case LevelInfo: 57 return zapcore.InfoLevel 58 case LevelWarn: 59 return zapcore.WarnLevel 60 case LevelDebug: 61 return zapcore.DebugLevel 62 case LevelError: 63 return zapcore.ErrorLevel 64 default: 65 return zapcore.InfoLevel 66 } 67 } 68 69 func makeEncoder(json bool) zapcore.Encoder { 70 encoderConfig := zap.NewProductionEncoderConfig() 71 if json { 72 return zapcore.NewJSONEncoder(encoderConfig) 73 } 74 75 encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 76 return zapcore.NewConsoleEncoder(encoderConfig) 77 } 78 79 func NewLogger(config *LoggerConfiguration) *Logger { 80 cores := []zapcore.Core{} 81 logger := &Logger{ 82 consoleLevel: zap.NewAtomicLevelAt(getZapLevel(config.ConsoleLevel)), 83 fileLevel: zap.NewAtomicLevelAt(getZapLevel(config.FileLevel)), 84 } 85 86 if config.EnableConsole { 87 writer := zapcore.Lock(os.Stdout) 88 core := zapcore.NewCore(makeEncoder(config.ConsoleJson), writer, logger.consoleLevel) 89 cores = append(cores, core) 90 } 91 92 if config.EnableFile { 93 writer := zapcore.AddSync(&lumberjack.Logger{ 94 Filename: config.FileLocation, 95 MaxSize: 100, 96 Compress: true, 97 }) 98 core := zapcore.NewCore(makeEncoder(config.FileJson), writer, logger.fileLevel) 99 cores = append(cores, core) 100 } 101 102 combinedCore := zapcore.NewTee(cores...) 103 104 logger.zap = zap.New(combinedCore, 105 zap.AddCaller(), 106 ) 107 108 return logger 109 } 110 111 func (l *Logger) ChangeLevels(config *LoggerConfiguration) { 112 l.consoleLevel.SetLevel(getZapLevel(config.ConsoleLevel)) 113 l.fileLevel.SetLevel(getZapLevel(config.FileLevel)) 114 } 115 116 func (l *Logger) SetConsoleLevel(level string) { 117 l.consoleLevel.SetLevel(getZapLevel(level)) 118 } 119 120 func (l *Logger) With(fields ...Field) *Logger { 121 newlogger := *l 122 newlogger.zap = newlogger.zap.With(fields...) 123 return &newlogger 124 } 125 126 func (l *Logger) StdLog(fields ...Field) *log.Logger { 127 return zap.NewStdLog(l.With(fields...).zap.WithOptions(getStdLogOption())) 128 } 129 130 // StdLogAt returns *log.Logger which writes to supplied zap logger at required level. 131 func (l *Logger) StdLogAt(level string, fields ...Field) (*log.Logger, error) { 132 return zap.NewStdLogAt(l.With(fields...).zap.WithOptions(getStdLogOption()), getZapLevel(level)) 133 } 134 135 // StdLogWriter returns a writer that can be hooked up to the output of a golang standard logger 136 // anything written will be interpreted as log entries accordingly 137 func (l *Logger) StdLogWriter() io.Writer { 138 newLogger := *l 139 newLogger.zap = newLogger.zap.WithOptions(zap.AddCallerSkip(4), getStdLogOption()) 140 f := newLogger.Info 141 return &loggerWriter{f} 142 } 143 144 func (l *Logger) WithCallerSkip(skip int) *Logger { 145 newlogger := *l 146 newlogger.zap = newlogger.zap.WithOptions(zap.AddCallerSkip(skip)) 147 return &newlogger 148 } 149 150 // Made for the plugin interface, wraps mlog in a simpler interface 151 // at the cost of performance 152 func (l *Logger) Sugar() *SugarLogger { 153 return &SugarLogger{ 154 wrappedLogger: l, 155 zapSugar: l.zap.Sugar(), 156 } 157 } 158 159 func (l *Logger) Debug(message string, fields ...Field) { 160 l.zap.Debug(message, fields...) 161 } 162 163 func (l *Logger) Info(message string, fields ...Field) { 164 l.zap.Info(message, fields...) 165 } 166 167 func (l *Logger) Warn(message string, fields ...Field) { 168 l.zap.Warn(message, fields...) 169 } 170 171 func (l *Logger) Error(message string, fields ...Field) { 172 l.zap.Error(message, fields...) 173 } 174 175 func (l *Logger) Critical(message string, fields ...Field) { 176 l.zap.Error(message, fields...) 177 }