mirror of https://github.com/dnomd343/XProxy.git
Dnomd343
1 year ago
5 changed files with 258 additions and 4 deletions
@ -0,0 +1,99 @@ |
|||||
|
package logger |
||||
|
|
||||
|
import ( |
||||
|
"bytes" |
||||
|
"fmt" |
||||
|
"github.com/gookit/color" |
||||
|
"go.uber.org/zap/zapcore" |
||||
|
"path/filepath" |
||||
|
"runtime" |
||||
|
"strconv" |
||||
|
"strings" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
// getGid get goroutine ID only for debugging.
|
||||
|
// -> https://blog.sgmansfield.com/2015/12/goroutine-ids/
|
||||
|
func getGid() uint64 { |
||||
|
b := make([]byte, 64) |
||||
|
b = b[:runtime.Stack(b, false)] |
||||
|
b = bytes.TrimPrefix(b, []byte("goroutine ")) |
||||
|
b = b[:bytes.IndexByte(b, ' ')] |
||||
|
n, _ := strconv.ParseUint(string(b), 10, 64) |
||||
|
return n |
||||
|
} |
||||
|
|
||||
|
// getCaller calculate relative source path of caller.
|
||||
|
func getCaller(ec zapcore.EntryCaller, verbose bool) string { |
||||
|
file, err := filepath.Rel(logHandle.path, ec.File) |
||||
|
if err != nil { |
||||
|
return "undefined" |
||||
|
} |
||||
|
if verbose { |
||||
|
return file + ":" + strconv.Itoa(ec.Line) |
||||
|
} |
||||
|
file, _ = strings.CutSuffix(file, ".go") // remove `.go` suffix
|
||||
|
return file |
||||
|
} |
||||
|
|
||||
|
// 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 custom prefix.
|
||||
|
func timeColoredEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { |
||||
|
enc.AppendString(fmt.Sprintf( |
||||
|
"%s %s", |
||||
|
color.Cyan.Render(logHandle.prefix), // colored prefix
|
||||
|
color.Gray.Render(t.Format("2006-01-02 15:04:05.000")), |
||||
|
)) |
||||
|
} |
||||
|
|
||||
|
// callerEncoder formats caller in square brackets.
|
||||
|
func callerEncoder(ec zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { |
||||
|
if !logHandle.verbose { |
||||
|
enc.AppendString("[" + getCaller(ec, false) + "]") |
||||
|
return |
||||
|
} |
||||
|
enc.AppendString(fmt.Sprintf("[%d] [%s]", getGid(), getCaller(ec, true))) |
||||
|
} |
||||
|
|
||||
|
// callerColoredEncoder formats caller in square brackets with
|
||||
|
// magenta color.
|
||||
|
func callerColoredEncoder(ec zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { |
||||
|
if !logHandle.verbose { |
||||
|
enc.AppendString(color.Magenta.Render("[" + getCaller(ec, false) + "]")) |
||||
|
return |
||||
|
} |
||||
|
enc.AppendString(fmt.Sprintf( |
||||
|
"%s %s", |
||||
|
color.Blue.Render(fmt.Sprintf("[%d]", getGid())), |
||||
|
color.Magenta.Render("["+getCaller(ec, true)+"]"), |
||||
|
)) |
||||
|
} |
||||
|
|
||||
|
// 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) |
||||
|
} |
@ -0,0 +1,59 @@ |
|||||
|
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 Debugf(template string, args ...interface{}) { |
||||
|
logHandle.sugar.Debugf(template, args...) |
||||
|
} |
||||
|
|
||||
|
func Infof(template string, args ...interface{}) { |
||||
|
logHandle.sugar.Infof(template, args...) |
||||
|
} |
||||
|
|
||||
|
func Warnf(template string, args ...interface{}) { |
||||
|
logHandle.sugar.Warnf(template, args...) |
||||
|
} |
||||
|
|
||||
|
func Errorf(template string, args ...interface{}) { |
||||
|
logHandle.sugar.Errorf(template, args...) |
||||
|
} |
||||
|
|
||||
|
func Panicf(template string, args ...interface{}) { |
||||
|
logHandle.sugar.Panicf(template, args...) |
||||
|
} |
||||
|
|
||||
|
// GetLevel return the current logger level.
|
||||
|
func GetLevel() zapcore.Level { |
||||
|
return logHandle.level.Level() |
||||
|
} |
||||
|
|
||||
|
// SetLevel configure logger output level. Note that debug level
|
||||
|
// will output more information and reduce performance.
|
||||
|
func SetLevel(level zapcore.Level) { |
||||
|
logHandle.level.SetLevel(level) |
||||
|
if level == DebugLevel { |
||||
|
logHandle.verbose = true |
||||
|
} else { |
||||
|
logHandle.verbose = false |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// AddOutputs adds more plain output channel to the logger module.
|
||||
|
func AddOutputs(outputs ...io.Writer) { |
||||
|
var writers []zapcore.WriteSyncer |
||||
|
for _, output := range outputs { |
||||
|
writers = append(writers, zapcore.AddSync(output)) |
||||
|
} |
||||
|
addWrites(writers...) |
||||
|
} |
@ -0,0 +1,78 @@ |
|||||
|
package logger |
||||
|
|
||||
|
import ( |
||||
|
"go.uber.org/zap" |
||||
|
"go.uber.org/zap/zapcore" |
||||
|
"os" |
||||
|
"path" |
||||
|
"runtime" |
||||
|
) |
||||
|
|
||||
|
type logger struct { |
||||
|
logger *zap.Logger |
||||
|
level *zap.AtomicLevel |
||||
|
sugar *zap.SugaredLogger |
||||
|
writers []zapcore.WriteSyncer |
||||
|
stderr zapcore.Core // fixed stderr output
|
||||
|
prefix string // custom output prefix
|
||||
|
path string // project absolute path
|
||||
|
verbose bool // show goroutine id and caller line
|
||||
|
} |
||||
|
|
||||
|
var logHandle *logger // singleton logger handle
|
||||
|
|
||||
|
// 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, |
||||
|
} |
||||
|
if colored { |
||||
|
config.EncodeTime = timeColoredEncoder |
||||
|
config.EncodeLevel = levelColoredEncoder |
||||
|
config.EncodeCaller = callerColoredEncoder |
||||
|
} |
||||
|
return config |
||||
|
} |
||||
|
|
||||
|
func init() { |
||||
|
zapLevel := zap.NewAtomicLevelAt(InfoLevel) // using info level in default
|
||||
|
zapCore := zapcore.NewCore( |
||||
|
zapcore.NewConsoleEncoder(logConfig(true)), // colorful output
|
||||
|
zapcore.Lock(os.Stderr), |
||||
|
zapLevel, |
||||
|
) |
||||
|
zapLogger := zap.New(zapCore, zap.AddCaller(), zap.AddCallerSkip(1)) |
||||
|
_, src, _, _ := runtime.Caller(0) // absolute path of current code
|
||||
|
logHandle = &logger{ |
||||
|
logger: zapLogger, |
||||
|
level: &zapLevel, |
||||
|
stderr: zapCore, |
||||
|
sugar: zapLogger.Sugar(), |
||||
|
writers: []zapcore.WriteSyncer{}, |
||||
|
path: path.Join(path.Dir(src), "../"), |
||||
|
prefix: "[XProxy]", |
||||
|
verbose: false, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// addWrites adds more plain log writers.
|
||||
|
func addWrites(writers ...zapcore.WriteSyncer) { |
||||
|
logHandle.writers = append(logHandle.writers, writers...) |
||||
|
plainCore := zapcore.NewCore( |
||||
|
zapcore.NewConsoleEncoder(logConfig(false)), // without colored
|
||||
|
zap.CombineWriteSyncers(logHandle.writers...), |
||||
|
logHandle.level, |
||||
|
) |
||||
|
logHandle.logger = zap.New( |
||||
|
zapcore.NewTee(logHandle.stderr, plainCore), |
||||
|
zap.AddCaller(), zap.AddCallerSkip(1), |
||||
|
) |
||||
|
logHandle.sugar = logHandle.logger.Sugar() |
||||
|
} |
Loading…
Reference in new issue