Refactor(log): use go.uber.org/zap (#389)

This commit is contained in:
Jason Lyu
2024-08-29 06:56:35 +08:00
committed by GitHub
parent c8c08cfeea
commit 601601a1dc
18 changed files with 136 additions and 489 deletions
+2
View File
@@ -0,0 +1,2 @@
// Package log is a thin wrapper based on "go.uber.org/zap".
package log
+16 -13
View File
@@ -1,7 +1,6 @@
package log
import (
"io"
"runtime"
"strings"
"time"
@@ -9,26 +8,30 @@ import (
glog "gvisor.dev/gvisor/pkg/log"
)
var _globalE = &emitter{}
func init() {
EnableStackLog(true)
glog.SetTarget(_globalE)
}
func EnableStackLog(v bool) {
if v {
glog.SetTarget(&emitter{}) // built-in logger
} else {
glog.SetTarget(&glog.Writer{Next: io.Discard})
}
type emitter struct {
logger *SugaredLogger
}
type emitter struct{}
func (e *emitter) setLogger(logger *SugaredLogger) {
e.logger = logger.WithOptions(pkgCallerSkip)
}
func (emitter) Emit(depth int, level glog.Level, _ time.Time, format string, args ...any) {
func (e *emitter) logf(level glog.Level, format string, args ...any) {
e.logger.Logf(1-Level(level), "[STACK] "+format, args...)
}
func (e *emitter) Emit(depth int, level glog.Level, _ time.Time, format string, args ...any) {
if _, file, line, ok := runtime.Caller(depth + 1); ok {
// Ignore (*gonet.TCPConn).RemoteAddr() warning: `ep.GetRemoteAddress() failed`.
if line == 457 && strings.HasSuffix(file, "/pkg/tcpip/adapters/gonet/gonet.go") {
// Ignore: gvisor.dev/gvisor/pkg/tcpip/adapters/gonet/gonet.go:457
if line == 457 && strings.HasSuffix(file, "gonet/gonet.go") {
return
}
}
logf(Level(level)+2, "[STACK] "+format, args...)
e.logf(level, format, args...)
}
-39
View File
@@ -1,39 +0,0 @@
package log
import (
"fmt"
"time"
"github.com/xjasonlyu/tun2socks/v2/common/observable"
)
var (
_logCh = make(chan any)
_source = observable.NewObservable(_logCh)
)
type Event struct {
Level Level `json:"level"`
Message string `json:"msg"`
Time time.Time `json:"time"`
}
func newEvent(level Level, format string, args ...any) *Event {
event := &Event{
Level: level,
Time: time.Now(),
Message: fmt.Sprintf(format, args...),
}
_logCh <- event /* send all events to logCh */
return event
}
func Subscribe() observable.Subscription {
sub, _ := _source.Subscribe()
return sub
}
func UnSubscribe(sub observable.Subscription) {
_source.UnSubscribe(sub)
}
+18 -59
View File
@@ -1,72 +1,31 @@
package log
import (
"encoding/json"
"fmt"
"strings"
"go.uber.org/zap/zapcore"
)
type Level uint32
// Level is an alias for zapcore.Level.
type Level = zapcore.Level
// Levels are aliases for Level.
const (
SilentLevel Level = iota
ErrorLevel
WarnLevel
InfoLevel
DebugLevel
DebugLevel = zapcore.DebugLevel
InfoLevel = zapcore.InfoLevel
WarnLevel = zapcore.WarnLevel
ErrorLevel = zapcore.ErrorLevel
DPanicLevel = zapcore.DPanicLevel
PanicLevel = zapcore.PanicLevel
FatalLevel = zapcore.FatalLevel
InvalidLevel = zapcore.InvalidLevel
SilentLevel = InvalidLevel + 1
)
// UnmarshalJSON deserialize Level with json
func (level *Level) UnmarshalJSON(data []byte) error {
var lvl string
if err := json.Unmarshal(data, &lvl); err != nil {
return err
}
l, err := ParseLevel(lvl)
if err != nil {
return err
}
*level = l
return nil
}
// MarshalJSON serialize Level with json
func (level Level) MarshalJSON() ([]byte, error) {
return json.Marshal(level.String())
}
func (level Level) String() string {
switch level {
case DebugLevel:
return "debug"
case InfoLevel:
return "info"
case WarnLevel:
return "warning"
case ErrorLevel:
return "error"
case SilentLevel:
return "silent"
default:
return fmt.Sprintf("not a valid level %d", level)
}
}
func ParseLevel(lvl string) (Level, error) {
switch strings.ToLower(lvl) {
case "silent":
// ParseLevel is a thin wrapper for zapcore.ParseLevel.
func ParseLevel(text string) (Level, error) {
switch text {
case "silent", "SILENT":
return SilentLevel, nil
case "error":
return ErrorLevel, nil
case "warning":
return WarnLevel, nil
case "info":
return InfoLevel, nil
case "debug":
return DebugLevel, nil
default:
return Level(0), fmt.Errorf("not a valid logrus Level: %q", lvl)
return zapcore.ParseLevel(text)
}
}
+58 -50
View File
@@ -1,63 +1,71 @@
package log
import (
"io"
"os"
"fmt"
"sync"
"github.com/sirupsen/logrus"
"go.uber.org/atomic"
"go.uber.org/zap"
)
// _defaultLevel is package default logging level.
var _defaultLevel = atomic.NewUint32(uint32(InfoLevel))
// global Logger and SugaredLogger.
var (
_globalMu sync.RWMutex
_globalL *Logger
_globalS *SugaredLogger
)
func init() {
logrus.SetOutput(os.Stdout)
logrus.SetLevel(logrus.DebugLevel)
SetLogger(zap.Must(zap.NewProduction()))
}
func SetOutput(out io.Writer) {
logrus.SetOutput(out)
}
func SetLevel(level Level) {
_defaultLevel.Store(uint32(level))
}
func Debugf(format string, args ...any) {
logf(DebugLevel, format, args...)
}
func Infof(format string, args ...any) {
logf(InfoLevel, format, args...)
}
func Warnf(format string, args ...any) {
logf(WarnLevel, format, args...)
}
func Errorf(format string, args ...any) {
logf(ErrorLevel, format, args...)
}
func Fatalf(format string, args ...any) {
logrus.Fatalf(format, args...)
}
func logf(level Level, format string, args ...any) {
event := newEvent(level, format, args...)
if uint32(event.Level) > _defaultLevel.Load() {
return
}
switch level {
func NewLeveled(l Level, options ...Option) (*Logger, error) {
switch l {
case SilentLevel:
return zap.NewNop(), nil
case DebugLevel:
logrus.WithTime(event.Time).Debugln(event.Message)
case InfoLevel:
logrus.WithTime(event.Time).Infoln(event.Message)
case WarnLevel:
logrus.WithTime(event.Time).Warnln(event.Message)
case ErrorLevel:
logrus.WithTime(event.Time).Errorln(event.Message)
return zap.NewDevelopment(options...)
case InfoLevel, WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, FatalLevel:
cfg := zap.NewProductionConfig()
cfg.Level.SetLevel(l)
return cfg.Build(options...)
default:
return nil, fmt.Errorf("invalid level: %s", l)
}
}
// SetLogger sets the global Logger and SugaredLogger.
func SetLogger(logger *Logger) {
_globalMu.Lock()
defer _globalMu.Unlock()
// apply pkgCallerSkip to global loggers.
_globalL = logger.WithOptions(pkgCallerSkip)
_globalS = _globalL.Sugar()
_globalE.setLogger(_globalS)
}
func logf(lvl Level, template string, args ...any) {
_globalMu.RLock()
s := _globalS
_globalMu.RUnlock()
s.Logf(lvl, template, args...)
}
func Debugf(template string, args ...any) {
logf(DebugLevel, template, args...)
}
func Infof(template string, args ...any) {
logf(InfoLevel, template, args...)
}
func Warnf(template string, args ...any) {
logf(WarnLevel, template, args...)
}
func Errorf(template string, args ...any) {
logf(ErrorLevel, template, args...)
}
func Fatalf(template string, args ...any) {
logf(FatalLevel, template, args...)
}
+22
View File
@@ -0,0 +1,22 @@
package log
import (
"go.uber.org/zap"
)
// Must is an alias for zap.Must.
var Must = zap.Must
// logger aliases for zap.Logger and zap.SugaredLogger.
type (
Logger = zap.Logger
SugaredLogger = zap.SugaredLogger
)
type (
// Option is an alias for zap.Option.
Option = zap.Option
)
// pkgCallerSkip skips the pkg wrapper code as the caller.
var pkgCallerSkip = zap.AddCallerSkip(2)