summaryrefslogtreecommitdiffstats
path: root/mlog
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2018-04-27 12:49:45 -0700
committerGitHub <noreply@github.com>2018-04-27 12:49:45 -0700
commit686c2fbab7607d42183ae685a27ea3d7dce8c3f6 (patch)
tree53ed73cada57bc43f342ac10e2f842cddb095218 /mlog
parent2acbc77d78456d7ba76ceb687b18985d7d92f814 (diff)
downloadchat-686c2fbab7607d42183ae685a27ea3d7dce8c3f6.tar.gz
chat-686c2fbab7607d42183ae685a27ea3d7dce8c3f6.tar.bz2
chat-686c2fbab7607d42183ae685a27ea3d7dce8c3f6.zip
Structured logging (#8673)
* Implementing structured logging * Changes to en.json to allow refactor to run. * Fixing global logger * Structured logger initalization. * Add caller. * Do some log redirection. * Auto refactor * Cleaning up l4g reference and removing dependancy. * Removing junk. * Copyright headers. * Fixing tests * Revert "Changes to en.json to allow refactor to run." This reverts commit fd8249e99bcad0231e6ea65cd77c32aae9a54026. * Fixing some auto refactor strangeness and typo. * Making keys more human readable.
Diffstat (limited to 'mlog')
-rw-r--r--mlog/global.go42
-rw-r--r--mlog/log.go143
2 files changed, 185 insertions, 0 deletions
diff --git a/mlog/global.go b/mlog/global.go
new file mode 100644
index 000000000..91d5858a4
--- /dev/null
+++ b/mlog/global.go
@@ -0,0 +1,42 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package mlog
+
+import (
+ "go.uber.org/zap"
+ "go.uber.org/zap/zapcore"
+)
+
+var globalLogger *Logger
+
+func InitGlobalLogger(logger *Logger) {
+ globalLogger = logger
+ Debug = globalLogger.Debug
+ Info = globalLogger.Info
+ Warn = globalLogger.Warn
+ Error = globalLogger.Error
+ Critical = globalLogger.Critical
+}
+
+func RedirectStdLog(logger *Logger) {
+ zap.RedirectStdLogAt(logger.zap.With(zap.String("source", "stdlog")), zapcore.ErrorLevel)
+}
+
+type LogFunc func(string, ...Field)
+
+// DON'T USE THIS Modify the level on the app logger
+func GloballyDisableDebugLogForTest() {
+ globalLogger.consoleLevel.SetLevel(zapcore.ErrorLevel)
+}
+
+// DON'T USE THIS Modify the level on the app logger
+func GloballyEnableDebugLogForTest() {
+ globalLogger.consoleLevel.SetLevel(zapcore.DebugLevel)
+}
+
+var Debug LogFunc
+var Info LogFunc
+var Warn LogFunc
+var Error LogFunc
+var Critical LogFunc
diff --git a/mlog/log.go b/mlog/log.go
new file mode 100644
index 000000000..801030c6c
--- /dev/null
+++ b/mlog/log.go
@@ -0,0 +1,143 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package mlog
+
+import (
+ "log"
+ "os"
+
+ "go.uber.org/zap"
+ "go.uber.org/zap/zapcore"
+ "gopkg.in/natefinch/lumberjack.v2"
+)
+
+const (
+ // Very verbose messages for debugging specific issues
+ LevelDebug = "debug"
+ // Default log level, informational
+ LevelInfo = "info"
+ // Warnings are messages about possible issues
+ LevelWarn = "warn"
+ // Errors are messages about things we know are problems
+ LevelError = "error"
+)
+
+// Type and function aliases from zap to limit the libraries scope into MM code
+type Field = zapcore.Field
+
+var Int64 = zap.Int64
+var Int = zap.Int
+var String = zap.String
+
+type LoggerConfiguration struct {
+ EnableConsole bool
+ ConsoleJson bool
+ ConsoleLevel string
+ EnableFile bool
+ FileJson bool
+ FileLevel string
+ FileLocation string
+}
+
+type Logger struct {
+ zap *zap.Logger
+ consoleLevel zap.AtomicLevel
+ fileLevel zap.AtomicLevel
+}
+
+func getZapLevel(level string) zapcore.Level {
+ switch level {
+ case LevelInfo:
+ return zapcore.InfoLevel
+ case LevelWarn:
+ return zapcore.WarnLevel
+ case LevelDebug:
+ return zapcore.DebugLevel
+ case LevelError:
+ return zapcore.ErrorLevel
+ default:
+ return zapcore.InfoLevel
+ }
+}
+
+func NewLogger(config *LoggerConfiguration) *Logger {
+ cores := []zapcore.Core{}
+ logger := &Logger{
+ consoleLevel: zap.NewAtomicLevelAt(getZapLevel(config.ConsoleLevel)),
+ fileLevel: zap.NewAtomicLevelAt(getZapLevel(config.FileLevel)),
+ }
+
+ encoderConfig := zap.NewProductionEncoderConfig()
+ var encoder zapcore.Encoder
+ if config.ConsoleJson {
+ encoder = zapcore.NewJSONEncoder(encoderConfig)
+ } else {
+ encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
+ encoder = zapcore.NewConsoleEncoder(encoderConfig)
+ }
+
+ if config.EnableConsole {
+ writer := zapcore.Lock(os.Stdout)
+ core := zapcore.NewCore(encoder, writer, logger.consoleLevel)
+ cores = append(cores, core)
+ }
+
+ if config.EnableFile {
+ writer := zapcore.AddSync(&lumberjack.Logger{
+ Filename: config.FileLocation,
+ MaxSize: 100,
+ Compress: true,
+ })
+ core := zapcore.NewCore(encoder, writer, logger.fileLevel)
+ cores = append(cores, core)
+ }
+
+ combinedCore := zapcore.NewTee(cores...)
+
+ logger.zap = zap.New(combinedCore,
+ zap.AddCallerSkip(2),
+ zap.AddCaller(),
+ )
+
+ return logger
+}
+
+func (l *Logger) ChangeLevels(config *LoggerConfiguration) {
+ l.consoleLevel.SetLevel(getZapLevel(config.ConsoleLevel))
+ l.fileLevel.SetLevel(getZapLevel(config.FileLevel))
+}
+
+func (l *Logger) SetConsoleLevel(level string) {
+ l.consoleLevel.SetLevel(getZapLevel(level))
+}
+
+func (l *Logger) With(fields ...Field) *Logger {
+ newlogger := *l
+ newlogger.zap = newlogger.zap.With(fields...)
+ return &newlogger
+}
+
+func (l *Logger) StdLog(fields ...Field) *log.Logger {
+ return zap.NewStdLog(l.With(fields...).zap)
+}
+
+func (l *Logger) Debug(message string, fields ...Field) {
+ l.zap.Debug(message, fields...)
+}
+
+func (l *Logger) Info(message string, fields ...Field) {
+ l.zap.Info(message, fields...)
+}
+
+func (l *Logger) Warn(message string, fields ...Field) {
+ l.zap.Warn(message, fields...)
+}
+
+func (l *Logger) Error(message string, fields ...Field) {
+ l.zap.Error(message, fields...)
+}
+
+func (l *Logger) Critical(message string, fields ...Field) {
+ l.zap.Error(message, fields...)
+}