diff --git a/go.mod b/go.mod index 5782fe3..a819525 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,11 @@ require ( ) require ( + github.com/fatih/color v1.15.0 // indirect + github.com/gookit/color v1.5.4 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/stretchr/testify v1.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/next/logger/encoder.go b/next/logger/encoder.go new file mode 100644 index 0000000..f7e69e4 --- /dev/null +++ b/next/logger/encoder.go @@ -0,0 +1,58 @@ +package logger + +import ( + "fmt" + "github.com/gookit/color" + "go.uber.org/zap/zapcore" + "time" +) + +// 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")) +} + +// 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")), + )) +} + +// callerEncoder formats caller in square brackets. +func callerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString("[" + 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() + "]")) +} + +// levelEncoder formats log level using square brackets. +func levelEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString("[" + 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 new file mode 100644 index 0000000..8e34adb --- /dev/null +++ b/next/logger/interface.go @@ -0,0 +1,51 @@ +package logger + +import ( + "go.uber.org/zap/zapcore" + "io" +) + +const ( + DebugLevel = zapcore.DebugLevel + InfoLevel = zapcore.InfoLevel + WarnLevel = zapcore.WarnLevel + ErrorLevel = zapcore.ErrorLevel + PanicLevel = zapcore.PanicLevel +) + +func GetLevel() zapcore.Level { + return handle.level.Level() +} + +func SetLevel(level zapcore.Level) { + handle.level.SetLevel(level) +} + +func Debugf(template string, args ...interface{}) { + handle.sugar.Debugf(template, args...) +} + +func Infof(template string, args ...interface{}) { + handle.sugar.Infof(template, args...) +} + +func Warnf(template string, args ...interface{}) { + handle.sugar.Warnf(template, args...) +} + +func Errorf(template string, args ...interface{}) { + handle.sugar.Errorf(template, args...) +} + +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 e7360c3..15b5fd3 100644 --- a/next/logger/logger.go +++ b/next/logger/logger.go @@ -1,134 +1,68 @@ package logger import ( - "fmt" "go.uber.org/zap" + "go.uber.org/zap/zapcore" "os" - "time" ) -import "go.uber.org/zap/zapcore" -var Logger *zap.SugaredLogger - -const ( - logTmFmt = "2006-01-02 15:04:05" -) - -func init() { - - //coreConfig := zapcore.EncoderConfig{ - // TimeKey: "ts", - // LevelKey: "level", - // NameKey: "logger", - // CallerKey: "caller", - // FunctionKey: zapcore.OmitKey, - // MessageKey: "msg", - // StacktraceKey: "stacktrace", - // LineEnding: zapcore.DefaultLineEnding, // 默认换行符"\n" - // EncodeLevel: zapcore.CapitalColorLevelEncoder, - // EncodeTime: zapcore.RFC3339TimeEncoder, // 日志时间格式显示 - // EncodeDuration: zapcore.MillisDurationEncoder, // 时间序列化,Duration为经过的浮点秒数 - // EncodeCaller: zapcore.ShortCallerEncoder, // 日志行号显示 - //} - // - //encoder := zapcore.NewConsoleEncoder(coreConfig) - // - //newCore := zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zapcore.DebugLevel) - // - //logger := zap.New(newCore) - // - //Logger = logger.Sugar() - - GetLogger() - - //log, err := zap.NewDevelopment() - //if err != nil { - // panic("log utils init failed") - //} - - // TODO: more zap logger configure - // TODO: reserve raw logger handle - - //Logger = log.Sugar() +type Logger struct { + logger *zap.Logger + level *zap.AtomicLevel + sugar *zap.SugaredLogger + writers []zapcore.WriteSyncer + stdCore zapcore.Core } -func GetLogger() { - config := zapcore.EncoderConfig{ - MessageKey: "M", - LevelKey: "L", - TimeKey: "T", - NameKey: "N", - CallerKey: "C", - FunctionKey: "F", - StacktraceKey: "S", - SkipLineEnding: false, - LineEnding: "\n", - - EncodeLevel: logEncodeLevel, - //EncodeLevel: zapcore.CapitalColorLevelEncoder, - EncodeTime: logEncodeTime, - EncodeDuration: zapcore.StringDurationEncoder, - //EncodeCaller: logEncodeCaller, - EncodeCaller: zapcore.ShortCallerEncoder, +var handle Logger - //EncodeName: logEncodeName, +// 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: timeEncoder, + EncodeLevel: levelEncoder, + EncodeCaller: callerEncoder, } - - //var zc = zap.Config{ - // Level: zap.NewAtomicLevelAt(zapcore.DebugLevel), - // Development: false, - // DisableCaller: false, - // DisableStacktrace: false, - // Sampling: nil, - // Encoding: "json", - // EncoderConfig: config, - // OutputPaths: []string{"stdout"}, - // ErrorOutputPaths: []string{"stderr"}, - // InitialFields: map[string]interface{}{"app": "zapdex"}, - //} - - newCore := zapcore.NewCore(zapcore.NewConsoleEncoder(config), zapcore.Lock(os.Stderr), zapcore.DebugLevel) - //newCore := zapcore.NewCore(zapcore.NewJSONEncoder(config), zapcore.Lock(os.Stderr), zapcore.DebugLevel) - logger := zap.New(newCore, zap.AddCaller()) - //logger := zap.New(newCore) - //logger, _ := zc.Build() - //logger.Named("123") - //fmt.Println(logger.Name()) - - zap.ReplaceGlobals(logger) - Logger = logger.Sugar() -} - -func logEncodeLevel(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(func(level zapcore.Level) string { - levelStr := level.CapitalString() - // TODO: using shell codes map - switch level { - case zapcore.DebugLevel: - return fmt.Sprintf("\x1b[39m[%s]\x1b[0m", levelStr) - case zapcore.InfoLevel: - return fmt.Sprintf("\x1b[32m[%s]\x1b[0m", levelStr) - case zapcore.WarnLevel: - return fmt.Sprintf("\x1b[33m[%s]\x1b[0m", levelStr) - case zapcore.ErrorLevel: - return fmt.Sprintf("\x1b[31m[%s]\x1b[0m", levelStr) - case zapcore.PanicLevel: - return fmt.Sprintf("\x1b[95m[%s]\x1b[0m", levelStr) - default: - return fmt.Sprintf("[%s]", levelStr) - } - }(level)) + if colored { + config.EncodeTime = timeColoredEncoder + config.EncodeLevel = levelColoredEncoder + config.EncodeCaller = callerColoredEncoder + } + return config } -func logEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) { - // TODO: using `2006-01-02 15:04:05.xxx` format - enc.AppendString(fmt.Sprintf( - "\x1b[36m%s\x1b[0m \x1b[90m%s\x1b[0m", - "[XProxy]", t.Format("2006-01-02 15:04:05"), - )) +func init() { + level := zap.NewAtomicLevelAt(DebugLevel) + core := zapcore.NewCore( + zapcore.NewConsoleEncoder(logConfig(true)), + zapcore.Lock(os.Stderr), level, + ) + logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)) + handle = Logger{ + logger: logger, + level: &level, + sugar: logger.Sugar(), + writers: []zapcore.WriteSyncer{}, + stdCore: core, + } } -func logEncodeCaller(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString("{" + caller.TrimmedPath() + "}") +// 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(), zap.AddCallerSkip(1), + ) + handle.sugar = handle.logger.Sugar() } diff --git a/next/main.go b/next/main.go index c4da370..b1b0001 100644 --- a/next/main.go +++ b/next/main.go @@ -2,7 +2,7 @@ package main import ( "XProxy/next/assets" - . "XProxy/next/logger" + "XProxy/next/logger" ) const gzSample = "/root/XProxy/LICENSE.gz" @@ -26,6 +26,6 @@ func main() { //raw, _ := assets.Download("https://cdn.dnomd343.top/v2ray-rules-dat/geosite.dat", "socks5://192.168.2.2:1084") raw, _ := assets.Download("https://cdn.dnomd343.top/v2ray-rules-dat/geosite.dat.xz", "") ret, _ := assets.Extract(raw) - Logger.Debugf("content size -> %d", len(ret)) + logger.Debugf("content size -> %d", len(ret)) }