add rotating log files daily feature; add file log config

master v0.0.3
ehlxr 2019-11-07 17:04:36 +08:00
parent 911f959018
commit b3fbc466f1
3 changed files with 59 additions and 35 deletions

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.13
require ( require (
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.8.1
github.com/robfig/cron/v3 v3.0.0
go.uber.org/zap v1.12.0 go.uber.org/zap v1.12.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0
) )

75
log.go
View File

@ -9,11 +9,11 @@ import (
"strings" "strings"
"time" "time"
"github.com/ehlxr/log/encoder"
"github.com/ehlxr/log/bufferpool" "github.com/ehlxr/log/bufferpool"
"github.com/ehlxr/log/crash" "github.com/ehlxr/log/crash"
"github.com/ehlxr/log/encoder"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/robfig/cron/v3"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )
@ -32,10 +32,9 @@ const (
type logConfig struct { type logConfig struct {
Level zapcore.Level Level zapcore.Level
FilePath string
EnableColors bool EnableColors bool
CrashLogPath string CrashLogFilename string
ErrorLogPath string ErrorLogFilename string
EnableLineNumber bool EnableLineNumber bool
// enable the truncation of the level text to 4 characters. // enable the truncation of the level text to 4 characters.
@ -45,21 +44,15 @@ type logConfig struct {
EnableCapitalLevel bool EnableCapitalLevel bool
atomicLevel zap.AtomicLevel atomicLevel zap.AtomicLevel
Name string Name string
*lumberjack.Logger
} }
func init() { func init() {
lc := &logConfig{ lc := &logConfig{
Level: InfoLevel, Logger: &lumberjack.Logger{
FilePath: "", LocalTime: true,
EnableColors: false, },
CrashLogPath: "",
ErrorLogPath: "",
EnableLineNumber: false,
EnableLevelTruncation: false,
EnableErrorStacktrace: false,
TimestampFormat: "",
EnableCapitalLevel: false,
Name: "",
} }
logger = lc.newLogger().Sugar() logger = lc.newLogger().Sugar()
@ -70,23 +63,32 @@ func (lc *logConfig) Init() {
} }
func NewLogConfig() *logConfig { func NewLogConfig() *logConfig {
return &logConfig{ config := &logConfig{
Level: DebugLevel, Level: DebugLevel,
FilePath: "./logs/",
EnableColors: true, EnableColors: true,
CrashLogPath: "./logs/crash.log", CrashLogFilename: "./logs/crash.log",
ErrorLogPath: "./logs/error_", ErrorLogFilename: "./logs/error.log",
EnableLineNumber: true, EnableLineNumber: true,
EnableLevelTruncation: true, EnableLevelTruncation: true,
EnableErrorStacktrace: true, EnableErrorStacktrace: true,
TimestampFormat: "2006-01-02 15:04:05.000", TimestampFormat: "2006-01-02 15:04:05.000",
EnableCapitalLevel: true, EnableCapitalLevel: true,
Logger: &lumberjack.Logger{
Filename: "./logs/log.log",
MaxSize: 200,
MaxAge: 0,
MaxBackups: 30,
LocalTime: true,
Compress: false,
},
} }
return config
} }
func (lc *logConfig) newLogger() *zap.Logger { func (lc *logConfig) newLogger() *zap.Logger {
if lc.CrashLogPath != "" { if lc.CrashLogFilename != "" {
writeCrashLog(lc.CrashLogPath) writeCrashLog(lc.CrashLogFilename)
} }
lc.atomicLevel = zap.NewAtomicLevelAt(lc.Level) lc.atomicLevel = zap.NewAtomicLevelAt(lc.Level)
@ -99,11 +101,11 @@ func (lc *logConfig) newLogger() *zap.Logger {
lc.atomicLevel, lc.atomicLevel,
)} )}
if lc.FilePath != "" { if lc.Filename != "" {
cores = append(cores, lc.fileCore()) cores = append(cores, lc.fileCore())
} }
if lc.ErrorLogPath != "" { if lc.ErrorLogFilename != "" {
cores = append(cores, lc.errorFileCore()) cores = append(cores, lc.errorFileCore())
} }
@ -164,7 +166,7 @@ func (lc *logConfig) fileCore() zapcore.Core {
// zapcore.Lock(os.Stdout), // zapcore.Lock(os.Stdout),
// lc.fileWriteSyncer(), // lc.fileWriteSyncer(),
// ), // ),
fileWriteSyncer(lc.FilePath), lc.fileWriteSyncer(lc.Filename),
lc.atomicLevel, lc.atomicLevel,
) )
} }
@ -173,7 +175,7 @@ func (lc *logConfig) errorFileCore() zapcore.Core {
return zapcore.NewCore( return zapcore.NewCore(
encoder.NewTextEncoder(lc.encoderConfig()), encoder.NewTextEncoder(lc.encoderConfig()),
fileWriteSyncer(lc.ErrorLogPath), lc.fileWriteSyncer(lc.ErrorLogFilename),
zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= zapcore.ErrorLevel return lvl >= zapcore.ErrorLevel
}), }),
@ -219,7 +221,7 @@ func trimCallerFilePath(ec zapcore.EntryCaller) string {
return fmt.Sprintf(" %s", caller) return fmt.Sprintf(" %s", caller)
} }
func fileWriteSyncer(name string) zapcore.WriteSyncer { func (lc *logConfig) fileWriteSyncer(fileName string) zapcore.WriteSyncer {
// go get github.com/lestrrat-go/file-rotatelogs // go get github.com/lestrrat-go/file-rotatelogs
// writer, err := rotatelogs.New( // writer, err := rotatelogs.New(
// name+".%Y%m%d", // name+".%Y%m%d",
@ -232,14 +234,21 @@ func fileWriteSyncer(name string) zapcore.WriteSyncer {
// } // }
writer := &lumberjack.Logger{ writer := &lumberjack.Logger{
Filename: fmt.Sprintf("%s%s.log", name, time.Now().Format("2006-01-02")), Filename: fileName,
MaxSize: 500, // 单个日志文件大小MB MaxSize: lc.MaxSize, // 单个日志文件大小MB
MaxBackups: 10, MaxBackups: lc.MaxBackups,
MaxAge: 30, // 保留多少天的日志 MaxAge: lc.MaxAge, // 保留多少天的日志
LocalTime: true, LocalTime: lc.LocalTime,
Compress: true, Compress: lc.Compress,
} }
// Rotating log files daily
runner := cron.New(cron.WithSeconds(), cron.WithLocation(time.UTC))
_, _ = runner.AddFunc("0 0 0 * * ? ", func() {
_ = writer.Rotate()
})
go runner.Run()
return zapcore.AddSync(writer) return zapcore.AddSync(writer)
} }

View File

@ -2,6 +2,7 @@ package log
import ( import (
"testing" "testing"
"time"
) )
func TestLog(t *testing.T) { func TestLog(t *testing.T) {
@ -11,11 +12,10 @@ func TestLog(t *testing.T) {
// Panicf("this is %s message", "panic") // Panicf("this is %s message", "panic")
} }
func TestLogWithConfig(t *testing.T) { func TestLogWithConfig(t *testing.T) {
lc := NewLogConfig() lc := NewLogConfig()
_ = lc.Level.Set("info") _ = lc.Level.Set("info")
lc.Name="main" lc.Name = "main"
lc.Init() lc.Init()
Debugf("this is %s message", "debug") Debugf("this is %s message", "debug")
@ -23,3 +23,17 @@ func TestLogWithConfig(t *testing.T) {
Errorf("this is %s message", "error") Errorf("this is %s message", "error")
// Panicf("this is %s message", "panic") // Panicf("this is %s message", "panic")
} }
func TestLogRote(t *testing.T) {
lc := NewLogConfig()
_ = lc.Level.Set("info")
lc.Name = "main"
lc.MaxSize = 1
lc.Init()
for {
Infof("this is %s message", "info")
time.Sleep(time.Second)
}
}