Go 配置zap日志,将zap日志库引入

By kcersing , 4 三月, 2023
package pkg

import (
"fmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
"os"
"time"
)

const (
outputDir = "../assets/log/"
outPath = "foot.log"
errPath = "foot.err"
)

var ZLog *ZapLogger

func init() {
ZLog = Logger()
}

type ZapLogger struct {
Log *zap.Logger
Sync func() error
}

func init() {
_, err := os.Stat(outputDir)
if err != nil {
if os.IsNotExist(err) {
err := os.Mkdir(outputDir, os.ModePerm)
if err != nil {
fmt.Printf("mkdir failed![%v]\n", err)
}
}
}
}

// Logger 配置zap日志,将zap日志库引入
func Logger() *ZapLogger {
//配置zap日志库的编码器
encoder := zapcore.EncoderConfig{
MessageKey: "msg",
LevelKey: "level",
TimeKey: "ts",
CallerKey: "caller",
StacktraceKey: "trace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
var cstSh, _ = time.LoadLocation("Local")
enc.AppendString(t.In(cstSh).Format("2006-01-02 15:04:05"))
},
EncodeName: zapcore.FullNameEncoder,
EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendInt64(int64(d) / 1000000)
},
}
return NewZapLogger(
encoder,
zap.NewAtomicLevelAt(zapcore.DebugLevel),
zap.AddStacktrace(
zap.NewAtomicLevelAt(zapcore.ErrorLevel)),
zap.AddCaller(),
zap.AddCallerSkip(2),
zap.Development(),
)
}

// 日志自动切割
func getLogWriter(filename string) zapcore.WriteSyncer {
//dataTime := time.Now().Format("2006_01_02_15_04_05")
yearTime := time.Now().Format("2006")
monthTime := time.Now().Format("01")
dayTime := time.Now().Format("02")

filenames := outputDir + yearTime + "/" + monthTime + "/" + dayTime + "_" + filename
lumberJackLogger := &lumberjack.Logger{
Filename: filenames, //指定日志存储位置
MaxSize: 10, //日志的最大大小(M)
MaxBackups: 8760, //日志的最大保存数量
MaxAge: 365, //日志文件存储最大天数
Compress: true, //是否执行压缩
}
return zapcore.AddSync(lumberJackLogger)
}

// NewZapLogger return a zap logger.
func NewZapLogger(encoder zapcore.EncoderConfig, level zap.AtomicLevel, opts ...zap.Option) *ZapLogger {
//设置日志级别
level.SetLevel(zap.InfoLevel)
var core zapcore.Core
// 实现两个判断日志等级的interface
infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return true
})
warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= zapcore.WarnLevel
})
infoHook1 := os.Stdout
infoHook2 := getLogWriter(outPath)
errorHook := getLogWriter(errPath)

core = zapcore.NewTee(
zapcore.NewCore(zapcore.NewJSONEncoder(encoder), zapcore.AddSync(infoHook1), infoLevel),
zapcore.NewCore(zapcore.NewJSONEncoder(encoder), zapcore.AddSync(infoHook2), infoLevel),
zapcore.NewCore(zapcore.NewJSONEncoder(encoder), zapcore.AddSync(errorHook), warnLevel),
)

// 开启开发模式,堆栈跟踪
caller := zap.AddCaller()
// 开启文件及行号
development := zap.Development()
//// 设置初始化字段
//filed := zap.Fields(zap.String("serviceName", "serviceName"))
// 构造日志
zapLogger := zap.New(core, caller, development, zap.AddStacktrace(zap.ErrorLevel))

//zapLogger := zap.New(core, opts...)
return &ZapLogger{Log: zapLogger, Sync: zapLogger.Sync}
}

// Log 实现log接口
func (l *ZapLogger) Logs(keyvals ...interface{}) error {
if len(keyvals) == 0 || len(keyvals)%2 != 0 {
l.Log.Warn(fmt.Sprint("Keyvalues must appear in pairs: ", keyvals))
return nil
}

var data []zap.Field
for i := 0; i < len(keyvals); i += 2 {
data = append(data, zap.Any(fmt.Sprint(keyvals[i]), keyvals[i+1]))
}

l.Log.Fatal("", data...)
return nil
}

标签