github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/logger/zap.go (about)

     1  package logger
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  
     8  	"go.uber.org/zap"
     9  	"go.uber.org/zap/zapcore"
    10  	"gopkg.in/natefinch/lumberjack.v2"
    11  )
    12  
    13  type zapLogger struct {
    14  	zap  *zap.Logger
    15  	opts Options
    16  }
    17  
    18  func (l *zapLogger) Init(opts ...Option) error {
    19  	for _, o := range opts {
    20  		o(&l.opts)
    21  	}
    22  
    23  	stdout := zapcore.Lock(os.Stdout) // lock for concurrent safe
    24  	stderr := zapcore.Lock(os.Stderr) // lock for concurrent safe
    25  
    26  	infoEnabler := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
    27  		return lvl >= getZapLevel(l.opts.Level) && lvl < zapcore.WarnLevel
    28  	})
    29  	warnEnabler := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
    30  		return lvl >= zapcore.WarnLevel
    31  	})
    32  
    33  	encoderCfg := zap.NewProductionEncoderConfig()
    34  	if l.opts.Debug {
    35  		encoderCfg = zap.NewDevelopmentEncoderConfig()
    36  	}
    37  
    38  	encoder := zapcore.NewConsoleEncoder(encoderCfg)
    39  	if l.opts.JsonEncoding {
    40  		encoder = zapcore.NewJSONEncoder(encoderCfg)
    41  	}
    42  
    43  	var cores []zapcore.Core
    44  	if !l.opts.DisableConsole {
    45  		consoleCore := zapcore.NewCore(
    46  			encoder,
    47  			zapcore.NewMultiWriteSyncer(stdout),
    48  			infoEnabler,
    49  		)
    50  		errorCore := zapcore.NewCore(
    51  			encoder,
    52  			zapcore.NewMultiWriteSyncer(stderr),
    53  			warnEnabler,
    54  		)
    55  		cores = append(cores, consoleCore, errorCore)
    56  	}
    57  
    58  	if l.opts.LogDir != "" {
    59  		if err := os.MkdirAll(l.opts.LogDir, 0766); err != nil {
    60  			return err
    61  		}
    62  		infoFile := zapcore.AddSync(l.fileSizeRotation(l.opts.LogDir + "info.log"))
    63  		warnFile := zapcore.AddSync(l.fileSizeRotation(l.opts.LogDir + "warn.log"))
    64  		infoCore := zapcore.NewCore(
    65  			encoder, zapcore.NewMultiWriteSyncer(infoFile),
    66  			infoEnabler,
    67  		)
    68  		warnCore := zapcore.NewCore(
    69  			encoder, zapcore.NewMultiWriteSyncer(warnFile),
    70  			warnEnabler,
    71  		)
    72  		cores = append(cores, infoCore, warnCore)
    73  	}
    74  
    75  	// 构造日志
    76  	l.zap = zap.New(
    77  		zapcore.NewTee(cores...),
    78  		zap.AddCaller(),
    79  		zap.AddCallerSkip(l.opts.CallerSkipCount),
    80  		zap.AddStacktrace(zapcore.ErrorLevel), // 记录当前日志级别的堆栈信息
    81  		zap.ErrorOutput(stderr),
    82  	)
    83  
    84  	if l.opts.Fields != nil {
    85  		fields := make([]zap.Field, 0, len(l.opts.Fields))
    86  		for k, v := range l.opts.Fields {
    87  			fields = append(fields, zap.Any(k, v))
    88  		}
    89  		l.zap = l.zap.With(fields...)
    90  	}
    91  	return nil
    92  }
    93  
    94  func (l *zapLogger) Fields(fields map[string]any) Logger {
    95  	data := make([]zap.Field, 0, len(fields))
    96  	for k, v := range fields {
    97  		data = append(data, zap.Any(k, v))
    98  	}
    99  
   100  	zl := &zapLogger{
   101  		zap:  l.zap.With(data...),
   102  		opts: l.opts,
   103  	}
   104  
   105  	return zl
   106  }
   107  
   108  func (l *zapLogger) Log(level string, v ...any) {
   109  	l.zap.Log(getZapLevel(level), fmt.Sprint(v...))
   110  }
   111  
   112  func (l *zapLogger) Logf(level string, format string, v ...any) {
   113  	l.zap.Log(getZapLevel(level), fmt.Sprintf(format, v...))
   114  }
   115  
   116  func (l *zapLogger) fileSizeRotation(file string) io.Writer {
   117  	return &lumberjack.Logger{
   118  		Filename:   file,
   119  		MaxSize:    l.opts.Rotation.MaxSize,
   120  		MaxBackups: l.opts.Rotation.MaxBackups,
   121  		MaxAge:     l.opts.Rotation.MaxAge,
   122  		LocalTime:  l.opts.Rotation.LocalTime,
   123  		Compress:   l.opts.Rotation.Compress,
   124  	}
   125  }
   126  
   127  // NewExampleLogger builds a Logger that's designed for use in zap's testable
   128  func NewExampleLogger() Logger {
   129  	return &zapLogger{
   130  		zap: zap.NewExample(),
   131  	}
   132  }
   133  
   134  // NewLogger New builds a new logger based on options.
   135  func NewLogger(opts ...Option) Logger {
   136  	l := &zapLogger{opts: _defOptions}
   137  	if err := l.Init(opts...); err != nil {
   138  		return nil
   139  	}
   140  
   141  	return l
   142  }
   143  
   144  // InitLogger init customize logger
   145  func InitLogger(opts ...Option) {
   146  	l := &zapLogger{opts: _defOptions}
   147  	if err := l.Init(opts...); err != nil {
   148  		panic(err)
   149  	}
   150  
   151  	logger = l
   152  }