Browse Source

Merge branch 'feature/logger' into feature/network

feature/network
Dnomd343 1 year ago
parent
commit
3c4bf1c655
  1. 8
      go.mod
  2. 18
      go.sum
  3. 99
      next/logger/encoder.go
  4. 59
      next/logger/interface.go
  5. 78
      next/logger/logger.go

8
go.mod

@ -5,14 +5,18 @@ go 1.21.0
require (
github.com/BurntSushi/toml v1.3.2
github.com/andybalholm/brotli v1.0.5
github.com/coreos/go-iptables v0.7.0
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a
github.com/gookit/color v1.5.4
github.com/klauspost/compress v1.16.7
github.com/robfig/cron v1.2.0
github.com/sirupsen/logrus v1.9.3
go.uber.org/zap v1.25.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/coreos/go-iptables v0.7.0 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sys v0.10.0 // indirect
)

18
go.sum

@ -2,6 +2,8 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8=
github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -9,6 +11,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a h1:v6zMvHuY9yue4+QkG/HQ/W67wvtQmWJ4SDo9aK/GIno=
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -18,10 +22,20 @@ github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfm
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

99
next/logger/encoder.go

@ -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)
}

59
next/logger/interface.go

@ -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...)
}

78
next/logger/logger.go

@ -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…
Cancel
Save