From 29ad4e4b84994e4454db2b26470e3a95bfb84c27 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Thu, 7 Sep 2023 01:36:40 +0800 Subject: [PATCH] feat: log module supports multiple outputs --- next/logger/encoder.go | 62 +++++++++++++++++++++++---------------- next/logger/interface.go | 14 ++++++++- next/logger/logger.go | 63 ++++++++++++++++++++++------------------ next/main.go | 30 +++++++++++++++---- 4 files changed, 110 insertions(+), 59 deletions(-) diff --git a/next/logger/encoder.go b/next/logger/encoder.go index 546358c..f7e69e4 100644 --- a/next/logger/encoder.go +++ b/next/logger/encoder.go @@ -1,46 +1,58 @@ package logger import ( - "github.com/fatih/color" + "fmt" + "github.com/gookit/color" "go.uber.org/zap/zapcore" "time" ) -func encodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) { +// timeEncoder formats the time as a string. +func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { enc.AppendString(t.Format("2006-01-02 15:04:05.000")) } -func encodeColoredTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(color.WhiteString(t.Format("2006-01-02 15:04:05.000"))) +// timeColoredEncoder formats the time as a colored string +// with `[XProxy]` prefix. +func timeColoredEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(fmt.Sprintf( + "%s %s", + color.Cyan.Render("[XProxy]"), + color.Gray.Render(t.Format("2006-01-02 15:04:05.000")), + )) } -func encodeCaller(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { +// callerEncoder formats caller in square brackets. +func callerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { enc.AppendString("[" + caller.TrimmedPath() + "]") } -func encodeColoredCaller(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(color.MagentaString("[" + caller.TrimmedPath() + "]")) +// callerColoredEncoder formats caller in square brackets +// with magenta color. +func callerColoredEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(color.Magenta.Render("[" + caller.TrimmedPath() + "]")) } -func encodeLevel(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { +// levelEncoder formats log level using square brackets. +func levelEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { enc.AppendString("[" + level.CapitalString() + "]") } -func encodeColoredLevel(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(func(level zapcore.Level) func(string, ...interface{}) string { - switch level { - case zapcore.DebugLevel: - return color.CyanString - case zapcore.InfoLevel: - return color.GreenString - case zapcore.WarnLevel: - return color.YellowString - case zapcore.ErrorLevel: - return color.RedString - case zapcore.PanicLevel: - return color.HiRedString - default: - return color.WhiteString - } - }(level)("[" + level.CapitalString() + "]")) +// levelColoredEncoder formats log level using square brackets +// and uses different colors. +func levelColoredEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { + levelStr := "[" + level.CapitalString() + "]" + switch level { + case zapcore.DebugLevel: + levelStr = color.FgDefault.Render(levelStr) + case zapcore.InfoLevel: + levelStr = color.Green.Render(levelStr) + case zapcore.WarnLevel: + levelStr = color.Yellow.Render(levelStr) + case zapcore.ErrorLevel: + levelStr = color.Red.Render(levelStr) + case zapcore.PanicLevel: + levelStr = color.LightRed.Render(levelStr) + } + enc.AppendString(levelStr) } diff --git a/next/logger/interface.go b/next/logger/interface.go index cc86407..8e34adb 100644 --- a/next/logger/interface.go +++ b/next/logger/interface.go @@ -1,6 +1,9 @@ package logger -import "go.uber.org/zap/zapcore" +import ( + "go.uber.org/zap/zapcore" + "io" +) const ( DebugLevel = zapcore.DebugLevel @@ -37,3 +40,12 @@ func Errorf(template string, args ...interface{}) { func Panicf(template string, args ...interface{}) { handle.sugar.Panicf(template, args...) } + +// AddOutputs adds more plain log outputs. +func AddOutputs(outputs ...io.Writer) { + var writers []zapcore.WriteSyncer + for _, output := range outputs { + writers = append(writers, zapcore.AddSync(output)) + } + addWrites(writers...) +} diff --git a/next/logger/logger.go b/next/logger/logger.go index 320149d..a778b83 100644 --- a/next/logger/logger.go +++ b/next/logger/logger.go @@ -3,59 +3,66 @@ package logger import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" + "os" ) type Logger struct { - logger *zap.Logger - level *zap.AtomicLevel - sugar *zap.SugaredLogger + logger *zap.Logger + level *zap.AtomicLevel + sugar *zap.SugaredLogger + writers []zapcore.WriteSyncer + stdCore zapcore.Core } var handle Logger -func logConfig(level zap.AtomicLevel, colored bool) zapcore.EncoderConfig { +// logConfig generates log config for XProxy. +func logConfig(colored bool) zapcore.EncoderConfig { config := zapcore.EncoderConfig{ ConsoleSeparator: " ", MessageKey: "msg", LevelKey: "level", TimeKey: "time", CallerKey: "caller", - EncodeTime: encodeTime, - EncodeLevel: encodeLevel, - EncodeCaller: encodeCaller, + EncodeTime: timeEncoder, + EncodeLevel: levelEncoder, + EncodeCaller: callerEncoder, } if colored { - config.EncodeTime = encodeColoredTime - config.EncodeLevel = encodeColoredLevel - config.EncodeCaller = encodeColoredCaller + config.EncodeTime = timeColoredEncoder + config.EncodeLevel = levelColoredEncoder + config.EncodeCaller = callerColoredEncoder } return config } func init() { - level := zap.NewAtomicLevelAt(DebugLevel) - - writer, _, _ := zap.Open("/dev/stderr", "/root/XProxy/next/lalala.log") - core := zapcore.NewCore( - zapcore.NewConsoleEncoder(logConfig(level, false)), - //zapcore.Lock(os.Stderr), - writer, - level, + zapcore.NewConsoleEncoder(logConfig(true)), + zapcore.Lock(os.Stderr), level, ) - - //zapcore.AddSync() - //zap.Open() - - //return core - logger := zap.New(core, zap.AddCaller()) - handle = Logger{ - logger: logger, - level: &level, - sugar: logger.Sugar(), + logger: logger, + level: &level, + sugar: logger.Sugar(), + writers: []zapcore.WriteSyncer{}, + stdCore: core, } +} +// addWrites adds more plain log writers. +func addWrites(writers ...zapcore.WriteSyncer) { + handle.writers = append(handle.writers, writers...) + plainCore := zapcore.NewCore( + zapcore.NewConsoleEncoder(logConfig(false)), + zap.CombineWriteSyncers(handle.writers...), + handle.level, + ) + handle.logger = zap.New( + zapcore.NewTee(handle.stdCore, plainCore), + zap.AddCaller(), + ) + handle.sugar = handle.logger.Sugar() } diff --git a/next/main.go b/next/main.go index 6fd8c1c..4640261 100644 --- a/next/main.go +++ b/next/main.go @@ -1,13 +1,33 @@ package main -import "XProxy/next/logger" +import ( + "XProxy/next/logger" + "os" +) func main() { - logger.Debugf("here is %s level", "debug") - logger.Infof("here is %s level", "info") - logger.Warnf("here is %s level", "warn") - logger.Errorf("here is %s level", "error") + //logger.Debugf("here is %s level", "debug") + //logger.Infof("here is %s level", "info") + //logger.Warnf("here is %s level", "warn") + //logger.Errorf("here is %s level", "error") //logger.Panicf("here is %s level", "panic") + fp1, _ := os.Create("demo_1.log") + fp2, _ := os.Create("demo_2.log") + fp3, _ := os.Create("demo_3.log") + + logger.Debugf("output msg 1 at debug") + logger.Infof("output msg 1 at info") + logger.Warnf("output msg 1 at warn") + logger.AddOutputs(fp1, fp2) + logger.SetLevel(logger.InfoLevel) + logger.Debugf("output msg 2 at debug") + logger.Infof("output msg 2 at info") + logger.Warnf("output msg 2 at warn") + logger.SetLevel(logger.WarnLevel) + logger.AddOutputs(fp3) + logger.Debugf("output msg 3 at debug") + logger.Infof("output msg 3 at info") + logger.Warnf("output msg 3 at warn") }