按不同的日志级别存储到不同的日志文件中(这里只实现了info和error级别)
控制最多保留的日志文件及保留最近多少天的日志文件(控制日志的最大磁盘使用量)
控制每个日志文件的大小
我们使用zap和lumberjack框架实现
go get -u go.uber.org/zap
go get gopkg.in/natefinch/lumberjack.v2
lumberjack的Logger结构体如下
type Logger struct {
//写日志的文件名称
Filename string `json:"filename" yaml:"filename"`
//每个日志文件长度的最大大小,默认100M。
MaxSize int `json:"maxsize" yaml:"maxsize"`
//日志保留的最大天数(只保留最近多少天的日志)
MaxAge int `json:"maxage" yaml:"maxage"`
//只保留最近多少个日志文件,用于控制程序总日志的大小
MaxBackups int `json:"maxbackups" yaml:"maxbackups"`
//是否使用本地时间,默认使用UTC时间
LocalTime bool `json:"localtime" yaml:"localtime"`
// 是否压缩日志文件,压缩方法gzip
Compress bool `json:"compress" yaml:"compress"`
size int64 //记录当前日志文件的字节数
file *os.File //当前的日志文件
mu sync.Mutex
millCh chan bool
startMill sync.Once
}
lumberjack的使用及源码可参考:https://mp.csdn.net/console/editor/html/107142274
package applog
import(
"strings"
"path/filepath"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
)
var (
infoLevel = "info"
errorLevel = "error"
debugLevel = "debug"
)
func NewLog(dir, prefix,level string,maxSize,maxBackups,maxAge int) (*zap.Logger, func(),error) {
if maxSize < 0 {
maxSize = 0
}
if maxBackups < 0 {
maxBackups = 0
}
if maxAge < 0 {
maxAge = 0
}
infoLog := &lumberjack.Logger{
Filename: getFilePath(dir, prefix, infoLevel),
MaxSize: maxSize,
MaxBackups: maxBackups,
MaxAge: maxAge,
LocalTime: true,
Compress: false,
}
errLog := &lumberjack.Logger{
Filename: getFilePath(dir, prefix, errorLevel),
MaxSize: maxSize,
MaxBackups: maxBackups,
MaxAge: maxAge,
LocalTime: true,
Compress: false,
}
cronLogger := &lumberLog{
dir:dir,
prefix: prefix,
level: level,
infoLog: infoLog,
errLog: errLog,
}
return cronLogger.getLoggerWithCron(), func() {cronLogger.StopLogger()},nil
}
func (l *lumberLog) rotate() {
if l.infoLog != nil {
l.infoLog.Rotate()
}
if l.errLog != nil {
l.errLog.Rotate()
}
}
type lumberLog struct {
dir string
prefix string
level string
infoLog *lumberjack.Logger
errLog *lumberjack.Logger
}
func (l *lumberLog) StopLogger() {
l.infoLog.Close()
l.errLog.Close()
}
func (l *lumberLog)getLoggerWithCron() (*zap.Logger) {
highPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool{
return lev >= zap.ErrorLevel
})
lowLevel := zap.InfoLevel
if strings.EqualFold(l.level,debugLevel) {
lowLevel = zap.DebugLevel
}
lowPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
return lev < zap.ErrorLevel && lev >= lowLevel
})
prodEncoder := zap.NewProductionEncoderConfig()
prodEncoder.EncodeTime = zapcore.ISO8601TimeEncoder
prodEncoder.CallerKey = ""
highCore := zapcore.NewCore(zapcore.NewJSONEncoder(prodEncoder),zapcore.AddSync(l.errLog),highPriority)
lowCore := zapcore.NewCore(zapcore.NewJSONEncoder(prodEncoder),zapcore.AddSync(l.infoLog),lowPriority)
return zap.New(zapcore.NewTee(highCore,lowCore))
}
func getFilePath(dir, prefile, level string) string {
return filepath.Join(dir,level,prefile+"-"+level)+".log"
}