Browse Source

Merge branch 'feature/logger' into feature/assets

# Conflicts:
#	next/main.go
feature/assets
Dnomd343 1 year ago
parent
commit
62504f58b8
  1. 57
      next/logger/encoder.go
  2. 36
      next/logger/interface.go
  3. 50
      next/logger/logger.go

57
next/logger/encoder.go

@ -1,36 +1,77 @@
package logger package logger
import ( import (
"bytes"
"fmt" "fmt"
"github.com/gookit/color" "github.com/gookit/color"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"path/filepath"
"runtime"
"strconv"
"strings"
"time" "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. // timeEncoder formats the time as a string.
func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05.000")) enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
} }
// timeColoredEncoder formats the time as a colored string // timeColoredEncoder formats the time as a colored string
// with `[XProxy]` prefix. // with custom prefix.
func timeColoredEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { func timeColoredEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(fmt.Sprintf( enc.AppendString(fmt.Sprintf(
"%s %s", "%s %s",
color.Cyan.Render("[XProxy]"), color.Cyan.Render(logHandle.prefix), // colored prefix
color.Gray.Render(t.Format("2006-01-02 15:04:05.000")), color.Gray.Render(t.Format("2006-01-02 15:04:05.000")),
)) ))
} }
// callerEncoder formats caller in square brackets. // callerEncoder formats caller in square brackets.
func callerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { func callerEncoder(ec zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString("[" + caller.TrimmedPath() + "]") 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 // callerColoredEncoder formats caller in square brackets with
// with magenta color. // magenta color.
func callerColoredEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) { func callerColoredEncoder(ec zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(color.Magenta.Render("[" + caller.TrimmedPath() + "]")) 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. // levelEncoder formats log level using square brackets.

36
next/logger/interface.go

@ -13,35 +13,43 @@ const (
PanicLevel = zapcore.PanicLevel 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{}) { func Debugf(template string, args ...interface{}) {
handle.sugar.Debugf(template, args...) logHandle.sugar.Debugf(template, args...)
} }
func Infof(template string, args ...interface{}) { func Infof(template string, args ...interface{}) {
handle.sugar.Infof(template, args...) logHandle.sugar.Infof(template, args...)
} }
func Warnf(template string, args ...interface{}) { func Warnf(template string, args ...interface{}) {
handle.sugar.Warnf(template, args...) logHandle.sugar.Warnf(template, args...)
} }
func Errorf(template string, args ...interface{}) { func Errorf(template string, args ...interface{}) {
handle.sugar.Errorf(template, args...) logHandle.sugar.Errorf(template, args...)
} }
func Panicf(template string, args ...interface{}) { func Panicf(template string, args ...interface{}) {
handle.sugar.Panicf(template, args...) 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 log outputs. // AddOutputs adds more plain output channel to the logger module.
func AddOutputs(outputs ...io.Writer) { func AddOutputs(outputs ...io.Writer) {
var writers []zapcore.WriteSyncer var writers []zapcore.WriteSyncer
for _, output := range outputs { for _, output := range outputs {

50
next/logger/logger.go

@ -4,17 +4,22 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"os" "os"
"path"
"runtime"
) )
type Logger struct { type logger struct {
logger *zap.Logger logger *zap.Logger
level *zap.AtomicLevel level *zap.AtomicLevel
sugar *zap.SugaredLogger sugar *zap.SugaredLogger
writers []zapcore.WriteSyncer writers []zapcore.WriteSyncer
stdCore zapcore.Core 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 handle Logger var logHandle *logger // singleton logger handle
// logConfig generates log config for XProxy. // logConfig generates log config for XProxy.
func logConfig(colored bool) zapcore.EncoderConfig { func logConfig(colored bool) zapcore.EncoderConfig {
@ -37,32 +42,37 @@ func logConfig(colored bool) zapcore.EncoderConfig {
} }
func init() { func init() {
level := zap.NewAtomicLevelAt(DebugLevel) zapLevel := zap.NewAtomicLevelAt(InfoLevel) // using info level in default
core := zapcore.NewCore( zapCore := zapcore.NewCore(
zapcore.NewConsoleEncoder(logConfig(true)), zapcore.NewConsoleEncoder(logConfig(true)), // colorful output
zapcore.Lock(os.Stderr), level, zapcore.Lock(os.Stderr),
zapLevel,
) )
logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)) zapLogger := zap.New(zapCore, zap.AddCaller(), zap.AddCallerSkip(1))
handle = Logger{ _, src, _, _ := runtime.Caller(0) // absolute path of current code
logger: logger, logHandle = &logger{
level: &level, logger: zapLogger,
sugar: logger.Sugar(), level: &zapLevel,
stderr: zapCore,
sugar: zapLogger.Sugar(),
writers: []zapcore.WriteSyncer{}, writers: []zapcore.WriteSyncer{},
stdCore: core, path: path.Join(path.Dir(src), "../"),
prefix: "[XProxy]",
verbose: false,
} }
} }
// addWrites adds more plain log writers. // addWrites adds more plain log writers.
func addWrites(writers ...zapcore.WriteSyncer) { func addWrites(writers ...zapcore.WriteSyncer) {
handle.writers = append(handle.writers, writers...) logHandle.writers = append(logHandle.writers, writers...)
plainCore := zapcore.NewCore( plainCore := zapcore.NewCore(
zapcore.NewConsoleEncoder(logConfig(false)), zapcore.NewConsoleEncoder(logConfig(false)), // without colored
zap.CombineWriteSyncers(handle.writers...), zap.CombineWriteSyncers(logHandle.writers...),
handle.level, logHandle.level,
) )
handle.logger = zap.New( logHandle.logger = zap.New(
zapcore.NewTee(handle.stdCore, plainCore), zapcore.NewTee(logHandle.stderr, plainCore),
zap.AddCaller(), zap.AddCallerSkip(1), zap.AddCaller(), zap.AddCallerSkip(1),
) )
handle.sugar = handle.logger.Sugar() logHandle.sugar = logHandle.logger.Sugar()
} }

Loading…
Cancel
Save