github.com/jlevesy/mattermost-server@v5.3.2-0.20181003190404-7468f35cb0c8+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.AddCallerSkip(1), 106 zap.AddCaller(), 107 ) 108 109 return logger 110 } 111 112 func (l *Logger) ChangeLevels(config *LoggerConfiguration) { 113 l.consoleLevel.SetLevel(getZapLevel(config.ConsoleLevel)) 114 l.fileLevel.SetLevel(getZapLevel(config.FileLevel)) 115 } 116 117 func (l *Logger) SetConsoleLevel(level string) { 118 l.consoleLevel.SetLevel(getZapLevel(level)) 119 } 120 121 func (l *Logger) With(fields ...Field) *Logger { 122 newlogger := *l 123 newlogger.zap = newlogger.zap.With(fields...) 124 return &newlogger 125 } 126 127 func (l *Logger) StdLog(fields ...Field) *log.Logger { 128 return zap.NewStdLog(l.With(fields...).zap.WithOptions(getStdLogOption())) 129 } 130 131 // StdLogWriter returns a writer that can be hooked up to the output of a golang standard logger 132 // anything written will be interpreted as log entries accordingly 133 func (l *Logger) StdLogWriter() io.Writer { 134 newLogger := *l 135 newLogger.zap = newLogger.zap.WithOptions(zap.AddCallerSkip(4), getStdLogOption()) 136 f := newLogger.Info 137 return &loggerWriter{f} 138 } 139 140 func (l *Logger) WithCallerSkip(skip int) *Logger { 141 newlogger := *l 142 newlogger.zap = newlogger.zap.WithOptions(zap.AddCallerSkip(skip)) 143 return &newlogger 144 } 145 146 // Made for the plugin interface, wraps mlog in a simpler interface 147 // at the cost of performance 148 func (l *Logger) Sugar() *SugarLogger { 149 return &SugarLogger{ 150 wrappedLogger: l, 151 zapSugar: l.zap.Sugar(), 152 } 153 } 154 155 func (l *Logger) Debug(message string, fields ...Field) { 156 l.zap.Debug(message, fields...) 157 } 158 159 func (l *Logger) Info(message string, fields ...Field) { 160 l.zap.Info(message, fields...) 161 } 162 163 func (l *Logger) Warn(message string, fields ...Field) { 164 l.zap.Warn(message, fields...) 165 } 166 167 func (l *Logger) Error(message string, fields ...Field) { 168 l.zap.Error(message, fields...) 169 } 170 171 func (l *Logger) Critical(message string, fields ...Field) { 172 l.zap.Error(message, fields...) 173 }