123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- package logger
- import (
- "fmt"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
- "gopkg.in/natefinch/lumberjack.v2"
- "io"
- "os"
- "sync"
- )
- var loggerInstance *Logger
- func init() {
- consoleCfg := zap.NewDevelopmentEncoderConfig()
- consoleCfg.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
- jsonCfg := zap.NewProductionEncoderConfig()
- jsonCfg.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
- loggerInstance = New(WithSkipCaller(2))
- loggerInstance.cores = append(loggerInstance.cores,
- zapcore.NewCore(zapcore.NewConsoleEncoder(consoleCfg), zapcore.AddSync(os.Stdout), loggerInstance.lv),
- )
- loggerInstance.flushLogger()
- }
- func GetInstance() *Logger {
- return loggerInstance
- }
- // Logger 是对 zap.SugaredLogger 的封装,简化其对外使用的接口,
- // 并且针对于 Logger 所有配置都是支持运行时动态修改,且并发安全。
- // Logger 也支持了针对于 zapcore.Core 的扩展,调用 Logger.AddCore 即可,
- //
- // 构建该对象请使用 New 进行创建,在该操作中会对部分必要属性进行初始化,
- // 直接使用结构体创建会导致结构体不可用(甚至panic)。
- //
- // 如非深度定制化扩展,非必要不建议使用 Logger.AddCore 进行扩展,该操作会
- // 导致客户端应用程序对zap包编译依赖,不保证切换内部日志实现。
- type Logger struct {
- // 日志打印用
- Logger zap.SugaredLogger
- // 互斥量
- // 用于内部不可并发逻辑使用
- lock *sync.Mutex
- // 当前日志打印级别
- // 借助zap内部级别设置机制,该机制
- // 内部使用乐观锁,协程安全
- lv zap.AtomicLevel
- // 所有的core
- cores []zapcore.Core
- writers []io.Writer
- *Options
- }
- func New(opts ...Option) *Logger {
- options := new(Options)
- if opts == nil || len(opts) == 0 {
- opts = []Option{WithSkipCaller(1)}
- }
- for _, opt := range opts {
- opt(options)
- }
- logger := &Logger{
- lock: &sync.Mutex{},
- lv: zap.NewAtomicLevelAt(zap.DebugLevel),
- Options: options,
- }
- logger.flushLogger()
- return logger
- }
- // Debug 格式化打印调试级别日志
- // 不同于zap内部可变参数逻辑,该可变参数是用于,字符串格式化的
- func (l *Logger) Debug(msg string, vs ...any) {
- if len(vs) == 0 {
- l.Logger.Debug(msg)
- return
- }
- l.Logger.Debugf(msg, vs...)
- }
- // Info 格式化打印信息级别日志
- // 不同于zap内部可变参数逻辑,该可变参数是用于,字符串格式化的
- func (l *Logger) Info(msg string, vs ...any) {
- if len(vs) == 0 {
- l.Logger.Info(msg)
- return
- }
- l.Logger.Infof(msg, vs...)
- }
- // Warn 格式化打印警告级别日志
- // 不同于zap内部可变参数逻辑,该可变参数是用于,字符串格式化的
- func (l *Logger) Warn(msg string, vs ...any) {
- if len(vs) == 0 {
- l.Logger.Warn(msg)
- return
- }
- l.Logger.Warnf(msg, vs...)
- }
- // Error 打印错误级别日志
- // 该方法具有两种传参形式:
- // 1. error类型:会直接格式化打印%+v日志
- // 2. 信息(格式化)
- // 3. error+格式化信息:error会作为 With 格式存在,且依旧以%+v格式输出
- func (l *Logger) Error(vs ...any) {
- if len(vs) == 0 {
- return
- }
- err, ok := vs[0].(error)
- if ok {
- if len(vs) == 1 {
- l.Logger.Errorf("%+v", err)
- return
- }
- withed := l.Logger.With(zap.String("err", fmt.Sprintf("%+v", err)))
- msg, ok := vs[1].(string)
- if ok {
- withed.Errorf(msg, vs[2:])
- return
- }
- withed.Error(vs[1:])
- return
- }
- msg, ok := vs[0].(string)
- if ok {
- if len(vs) > 1 {
- l.Logger.Errorf(msg, vs[1:]...)
- return
- }
- if len(vs) == 1 {
- l.Logger.Error(vs[0])
- return
- }
- }
- }
- // Lv 获取当前日志打印级别
- func (l *Logger) Lv() int8 {
- return int8(l.lv.Level())
- }
- // SetLv 设置当前日志打印级别
- func (l *Logger) SetLv(lv int8) {
- l.lv.SetLevel(zapcore.Level(lv))
- }
- // NewFileOutput 新增日志输出文件配置
- func (l *Logger) NewFileOutput(opts ...FileOutputOpt) {
- cfg := new(OutFileOptions)
- for _, opt := range opts {
- opt(cfg)
- }
- l.NewOutput(&lumberjack.Logger{
- Filename: cfg.filename,
- MaxSize: cfg.maxSize,
- MaxAge: cfg.maxAge,
- MaxBackups: cfg.maxBackups,
- LocalTime: cfg.localTime,
- Compress: cfg.compress,
- })
- }
- // NewOutput 新增日志输出位置
- func (l *Logger) NewOutput(writer io.Writer) {
- cfg := zap.NewProductionEncoderConfig()
- cfg.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
- l.writers = append(l.writers, writer)
- l.AddCore(zapcore.NewCore(zapcore.NewJSONEncoder(cfg), zapcore.AddSync(writer), l.lv))
- }
- // AddCore 添加Core
- func (l *Logger) AddCore(core ...zapcore.Core) {
- l.addCoreOnly(core...)
- l.flushLogger()
- }
- // Flush 将缓冲区日志刷新至目标
- func (l *Logger) Flush() {
- _ = l.Logger.Sync()
- }
- // 保存内部core(不负责刷新 logger)
- func (l *Logger) addCoreOnly(core ...zapcore.Core) {
- l.lock.Lock()
- defer l.lock.Unlock()
- l.cores = append(l.cores, core...)
- }
- func (l *Logger) clone() *Logger {
- newL := &Logger{cores: l.cores, lv: l.lv, Options: l.Options}
- newL.flushLogger()
- return newL
- }
- // 刷新内部 logger
- // 刷新互斥,触发刷新后,刷新完成前依旧按照旧的配置执行
- func (l *Logger) flushLogger() {
- l.lock.Lock()
- defer l.lock.Unlock()
- l.Logger = *zap.
- New(
- zapcore.NewTee(l.cores...),
- zap.AddCaller(),
- ).
- Sugar().
- WithOptions(
- zap.AddCallerSkip(l.skipCaller),
- zap.WithCaller(true),
- )
- }
|