github.com/nhannv/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  }