Browse Source

精简Logger结构,将输出端外移
支持基于Logger针对于zap的深度扩展

jys 1 year ago
parent
commit
485d2d1adf
5 changed files with 74 additions and 102 deletions
  1. 0 21
      core.go
  2. 0 15
      enums.go
  3. 35 5
      log.go
  4. 29 61
      logger.go
  5. 10 0
      opt.go

+ 0 - 21
core.go

@@ -1,21 +0,0 @@
-package fslog
-
-import (
-	"go.uber.org/zap/zapcore"
-	"io"
-)
-
-type CoreContext struct {
-	zapcore.Core
-	io.Writer
-}
-
-type coreContexts []CoreContext
-
-func (c coreContexts) Cores() []zapcore.Core {
-	cores := make([]zapcore.Core, len(c))
-	for i, core := range c {
-		cores[i] = core.Core
-	}
-	return cores
-}

+ 0 - 15
enums.go

@@ -16,18 +16,3 @@ const (
 func (l Level) zap() zapcore.Level {
 	return zapcore.Level(l)
 }
-
-// zapcore.Core 的分类枚举
-// 方便外部对默认core的改写、扩展
-type coreType uint8
-
-const (
-	// 控制台输出
-	console = iota
-	// 文件输出
-	output
-	// zap内置
-	system
-	// 用户定义
-	third
-)

+ 35 - 5
log.go

@@ -10,6 +10,12 @@ import (
 
 var log *Logger
 
+// 默认配置,准备了控制台、json文件两种输出方式
+var consoleEncoder zapcore.Encoder
+var jsonEncoder zapcore.Encoder
+var consoleSync zapcore.WriteSyncer
+var outputSync zapcore.WriteSyncer
+
 func init() {
 	consoleEncoderConfig := zap.NewDevelopmentEncoderConfig()
 	consoleEncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
@@ -24,7 +30,9 @@ func init() {
 		MaxAge:    10,
 		LocalTime: true,
 	})
-	log = NewLogger()
+
+	log = New()
+	log.AddCore(BuiltinConsoleCore(DebugLv), BuiltinOutputFileCore(DebugLv))
 }
 
 // With 见 Logger.With
@@ -33,23 +41,27 @@ func With(k string, v any) *Logger {
 }
 
 // Info 见 Logger.Info
-func Info(msg string, vs ...any) {
+func Info(msg string, vs ...any) *Logger {
 	log.Info(msg, vs...)
+	return log
 }
 
 // Debug 见 Logger.Debug
-func Debug(msg string, vs ...any) {
+func Debug(msg string, vs ...any) *Logger {
 	log.Debug(msg, vs...)
+	return log
 }
 
 // Warn 见 Logger.Warn
-func Warn(msg string, vs ...any) {
+func Warn(msg string, vs ...any) *Logger {
 	log.Warn(msg, vs...)
+	return log
 }
 
 // Error 见 Logger.Error
-func Error(vs ...any) {
+func Error(vs ...any) *Logger {
 	log.Error(vs...)
+	return log
 }
 
 // Lv 见 Logger.Lv
@@ -75,6 +87,24 @@ func NewOutput(writer io.Writer) *Logger {
 	return log
 }
 
+// SetLogger 替换fslog包默认的log对象
+// Logger 支持了很多zapcore级别的底层配置,见 Logger
+func SetLogger(logger *Logger) *Logger {
+	log = logger
+	return log
+}
+
+// Flush 见 Logger.Flush
 func Flush() {
 	log.Flush()
 }
+
+// BuiltinConsoleCore 获取内置的控制台输出 zapcore.Core
+func BuiltinConsoleCore(lv Level) zapcore.Core {
+	return zapcore.NewCore(consoleEncoder, consoleSync, lv.zap())
+}
+
+// BuiltinOutputFileCore 获取文件输出 zapcore.Core
+func BuiltinOutputFileCore(lv Level) zapcore.Core {
+	return zapcore.NewCore(jsonEncoder, outputSync, lv.zap())
+}

+ 29 - 61
logger.go

@@ -9,21 +9,15 @@ import (
 	"sync"
 )
 
-// 默认配置,准备了控制台、json文件两种输出方式
-var consoleEncoder zapcore.Encoder
-var jsonEncoder zapcore.Encoder
-var consoleSync zapcore.WriteSyncer
-var outputSync zapcore.WriteSyncer
-
-type outFileConfig struct {
-	filename   string
-	maxSize    int
-	maxAge     int
-	maxBackups int
-	localTime  bool
-	Compress   bool
-}
-
+// Logger 是对 zap.SugaredLogger 的封装,简化其对外使用的接口,
+// 并且针对于 Logger 所有配置都是支持运行时动态修改,且并发安全。
+// Logger 也支持了针对于 zapcore.Core 的扩展,调用 Logger.AddCore 即可,
+//
+// 构建该对象请使用 New 进行创建,在该操作中会对部分必要属性进行初始化,
+// 直接使用结构体创建会导致结构体不可用(甚至panic)。
+//
+// 如非深度定制化扩展,非必要不建议使用 Logger.AddCore 进行扩展,该操作会
+// 导致客户端应用程序对zap包编译依赖,不保证fslog切换内部日志实现。
 type Logger struct {
 	// 互斥量
 	// 用于内部不可并发逻辑使用
@@ -37,22 +31,14 @@ type Logger struct {
 	// 内部使用乐观锁,协程安全
 	lv zap.AtomicLevel
 
-	// zapcore.Core 映射,存储不同来源/用途的core创建
-	cores map[coreType][]CoreContext
+	// 所有的core
+	cores []zapcore.Core
 }
 
-func NewLogger() *Logger {
+func New() *Logger {
 	logger := new(Logger)
 	logger.lv = zap.NewAtomicLevelAt(zap.DebugLevel)
-	logger.setCore(console, CoreContext{
-		Core:   zapcore.NewCore(consoleEncoder, consoleSync, logger.lv),
-		Writer: consoleSync,
-	})
-	logger.setCore(output, CoreContext{
-		Core:   zapcore.NewCore(jsonEncoder, outputSync, logger.lv),
-		Writer: outputSync,
-	})
-	logger.flush()
+	logger.flushLogger()
 	return logger
 }
 
@@ -153,7 +139,7 @@ func (l *Logger) NewFileOutput(opts ...FileOutputOpt) {
 	for _, opt := range opts {
 		opt(cfg)
 	}
-	l.newOut(&lumberjack.Logger{
+	l.NewOutput(&lumberjack.Logger{
 		Filename:   cfg.filename,
 		MaxSize:    cfg.maxSize,
 		MaxAge:     cfg.maxAge,
@@ -165,61 +151,43 @@ func (l *Logger) NewFileOutput(opts ...FileOutputOpt) {
 
 // NewOutput 新增日志输出位置
 func (l *Logger) NewOutput(writer io.Writer) {
-	l.newOut(writer)
+	l.AddCore(zapcore.NewCore(jsonEncoder, zapcore.AddSync(writer), l.lv))
 }
 
 // AddCore 添加Core
-func (l *Logger) AddCore(core ...CoreContext) {
-	l.setCore(third, core...)
-	l.flush()
+func (l *Logger) AddCore(core ...zapcore.Core) {
+	l.addCoreOnly(core...)
+	l.flushLogger()
 }
 
 // Flush 将缓冲区日志刷新至目标
 func (l *Logger) Flush() {
 	err := l.logger.Sync()
 	if err != nil {
-		Warn("flush log error: %s", err.Error())
+		With("err", err.Error()).Warn("flushLogger log error")
 	}
 }
 
-// newOut 设置日志写出位置
-func (l *Logger) newOut(writer io.Writer) {
-	l.setCore(output, CoreContext{
-		Core:   zapcore.NewCore(jsonEncoder, zapcore.AddSync(writer), l.lv),
-		Writer: writer,
-	})
-	l.flush()
-}
-
 // 保存内部core(不负责刷新 logger)
-func (l *Logger) setCore(ct coreType, core ...CoreContext) {
+func (l *Logger) addCoreOnly(core ...zapcore.Core) {
 	l.lock.Lock()
 	defer l.lock.Unlock()
-	if l.cores == nil {
-		l.cores = make(map[coreType][]CoreContext)
-	}
-	l.cores[ct] = append(l.cores[ct], core...)
+	l.cores = append(l.cores, core...)
+}
+
+func (l *Logger) clone() *Logger {
+	newL := &Logger{cores: l.cores, lv: l.lv}
+	newL.flushLogger()
+	return newL
 }
 
 // 刷新内部 logger
 // 刷新互斥,触发刷新后,刷新完成前依旧按照旧的配置执行
-func (l *Logger) flush() {
+func (l *Logger) flushLogger() {
 	l.lock.Lock()
 	defer l.lock.Unlock()
-
-	cores := make(coreContexts, 0, len(l.cores))
-	for _, core := range l.cores {
-		cores = append(cores, core...)
-	}
-
 	l.logger = *zap.New(
-		zapcore.NewTee(cores.Cores()...),
+		zapcore.NewTee(l.cores...),
 		zap.AddCaller(),
 	).Sugar()
 }
-
-func (l *Logger) clone() *Logger {
-	newL := &Logger{cores: l.cores, lv: l.lv}
-	newL.flush()
-	return newL
-}

+ 10 - 0
opt.go

@@ -1,5 +1,15 @@
 package fslog
 
+type outFileConfig struct {
+	filename   string
+	maxSize    int
+	maxAge     int
+	maxBackups int
+	localTime  bool
+	Compress   bool
+}
+
+// FileOutputOpt 文件输出选项
 type FileOutputOpt func(*outFileConfig)
 
 func WithFilename(filename string) FileOutputOpt {