Browse Source

feat: add verbose option

dev
Dnomd343 10 months ago
parent
commit
f1618a3c4e
  1. 47
      next/logger/encoder.go
  2. 36
      next/logger/interface.go
  3. 52
      next/logger/logger.go
  4. 5
      next/main.go

47
next/logger/encoder.go

@ -5,14 +5,16 @@ import (
"fmt"
"github.com/gookit/color"
"go.uber.org/zap/zapcore"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
)
// getGID get goroutine ID only for debugging.
// getGid get goroutine ID only for debugging.
// -> https://blog.sgmansfield.com/2015/12/goroutine-ids/
func getGID() uint64 {
func getGid() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
@ -21,41 +23,54 @@ func getGID() uint64 {
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 `[XProxy]` prefix.
// with custom prefix.
func timeColoredEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(fmt.Sprintf(
"%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")),
))
}
// callerEncoder formats caller in square brackets.
func callerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
if !handle.gid {
enc.AppendString("[" + caller.TrimmedPath() + "]")
} else {
enc.AppendString(fmt.Sprintf("[%s] [%d]", caller.TrimmedPath(), getGID()))
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(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
if !handle.gid {
enc.AppendString(color.Magenta.Render("[" + caller.TrimmedPath() + "]"))
// 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.Magenta.Render("["+caller.TrimmedPath()+"]"),
color.Blue.Render(fmt.Sprintf("[%d]", getGID())),
color.Blue.Render(fmt.Sprintf("[%d]", getGid())),
color.Magenta.Render("["+getCaller(ec, true)+"]"),
))
}

36
next/logger/interface.go

@ -13,35 +13,43 @@ const (
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...)
logHandle.sugar.Debugf(template, args...)
}
func Infof(template string, args ...interface{}) {
handle.sugar.Infof(template, args...)
logHandle.sugar.Infof(template, args...)
}
func Warnf(template string, args ...interface{}) {
handle.sugar.Warnf(template, args...)
logHandle.sugar.Warnf(template, args...)
}
func Errorf(template string, args ...interface{}) {
handle.sugar.Errorf(template, args...)
logHandle.sugar.Errorf(template, args...)
}
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) {
var writers []zapcore.WriteSyncer
for _, output := range outputs {

52
next/logger/logger.go

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

5
next/main.go

@ -6,7 +6,6 @@ import (
)
func main() {
//logger.Debugf("here is %s level", "debug")
//logger.Infof("here is %s level", "info")
//logger.Warnf("here is %s level", "warn")
@ -30,4 +29,8 @@ func main() {
logger.Debugf("output msg 3 at debug")
logger.Infof("output msg 3 at info")
logger.Warnf("output msg 3 at warn")
logger.SetLevel(logger.DebugLevel)
logger.Debugf("output msg 4 at debug")
logger.Infof("output msg 4 at info")
logger.Warnf("output msg 4 at warn")
}

Loading…
Cancel
Save