From a072ff02debfe8eee82ac03a6b1190ef675ef489 Mon Sep 17 00:00:00 2001 From: Edward Tsang Date: Mon, 28 May 2018 13:49:56 -0700 Subject: [PATCH] hierarchal logging --- src/hierarchal-logging/README.md | 25 +++++++++++ src/hierarchal-logging/main.go | 73 ++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/hierarchal-logging/README.md create mode 100644 src/hierarchal-logging/main.go diff --git a/src/hierarchal-logging/README.md b/src/hierarchal-logging/README.md new file mode 100644 index 0000000..16ac878 --- /dev/null +++ b/src/hierarchal-logging/README.md @@ -0,0 +1,25 @@ +# Hierarchal Logging + +One way of simulating hierarchal logging is to rely of Cloning the parent logger and +replacing the settings you want to change and get the old reference point to the new logger. +The cloning process is never inplace. + +The keys are usage of zap.WrapCore, the introduced Clone and the Logger struct to wrap the underlying zap logger. + +Hierarachal logging can be using when you have multiple components that require differnt default logging +levels. + +When look at the examples, keep note of which ancestor loggers each children is cloned from. +Also, notice the extra wrapping required to retain the underlying zap logger semantics. +You can definitely want to investigate if wrapping Levels is required for more manipulations of Levels. + +```console +$ go run src/hierarchal-logging/main.go + +*** Create multiple hierachy of loggers on raw logger *** +You probably need to wrap SetLevel to deal with more level setting/resetting +parent child loggers are really copying parent logger then replace settings +{"level":"debug","ts":1527539781.3316631,"msg":"childlogger2 decends from parentLogger with Debug enabled. Debug Should print"} +{"level":"debug","ts":1527539781.3317158,"msg":"This child still inherits level from childLogger2. Debug Should print \n"} + +``` \ No newline at end of file diff --git a/src/hierarchal-logging/main.go b/src/hierarchal-logging/main.go new file mode 100644 index 0000000..dff5670 --- /dev/null +++ b/src/hierarchal-logging/main.go @@ -0,0 +1,73 @@ +package main + +import ( + "fmt" + "os" + + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type Level zapcore.Level +type Logger struct { + logger *zap.Logger + encoder zapcore.Encoder + writer zapcore.WriteSyncer +} + +func main() { + fmt.Printf("\n*** Create multiple hierachy of loggers on raw logger *** \n") + fmt.Printf("You probably need to wrap SetLevel to deal with more level setting/resetting\n") + + encoderConfig := zap.NewProductionEncoderConfig() + atomLevel := zap.NewAtomicLevelAt(zapcore.InfoLevel) + encoder := zapcore.NewJSONEncoder(encoderConfig) + writer := zapcore.Lock(os.Stdout) + + core := zapcore.NewCore(encoder, writer, &atomLevel) + logger := zap.New(core) + parentLogger := Logger{logger, encoder, writer} + parentLogger.Debug("Should not print") + fmt.Printf("parent child loggers are really copying parent logger then replace settings \n") + childLogger1 := parentLogger.Clone() + childLogger1.Debug("This child still inherits level from parent logger. Should not print \n") + childLogger2 := parentLogger.NewLevel(zapcore.DebugLevel) + childLogger2.Debug("childlogger2 decends from parentLogger with Debug enabled. Debug Should print") + childLogger3 := childLogger2.Clone() + childLogger3.Debug("This child still inherits level from childLogger2. Debug Should print \n") + childLogger4 := parentLogger.Clone() + childLogger4.Debug("This child still inherits level from original parentLogger. Debug Should not print \n") + // {"level":"debug","ts":1527539781.3316631,"msg":"childlogger2 decends from parentLogger with Debug enabled. Debug Should print"} + // {"level":"debug","ts":1527539781.3317158,"msg":"This child still inherits level from childLogger2. Debug Should print \n"} +} + +func (l *Logger) NewLevel(level zapcore.Level) *Logger { + newLevel := zapcore.Level(level) + newLogger := l.logger.WithOptions( + zap.WrapCore( + func(zapcore.Core) zapcore.Core { + return zapcore.NewCore(l.encoder, l.writer, newLevel) + })) + return &Logger{newLogger, l.encoder, l.writer} +} + +func (l *Logger) Debug(msg string) { + l.logger.Debug(msg) +} + +func (l *Logger) Info(msg string) { + l.logger.Info(msg) +} + +func (l *Logger) Error(msg string) { + l.logger.Error(msg) +} + +func (l *Logger) Fatal(msg string) { + l.logger.Fatal(msg) +} + +func (l *Logger) Clone() *Logger { + copy := *l + return © +}