diff --git a/raftstore/log_test.go b/raftstore/log_test.go new file mode 100644 index 000000000..fa4235089 --- /dev/null +++ b/raftstore/log_test.go @@ -0,0 +1,73 @@ +package raftstore + +import ( + "os" + "path" + "testing" + "time" +) + +// test auto remove raft log 7 days ago +func TestCleanRaftLog(t *testing.T) { + dir := path.Join("/tmp/raft", "logs") + _, err := os.Stat(dir) + if os.IsNotExist(err) { + os.MkdirAll(dir, 0755) + } + + logFilePath1 := path.Join(dir, "test_clean.log.old") + if err = createFile(logFilePath1, true); err != nil { + t.Errorf("create file[%v] err[%v]", logFilePath1, err) + return + } + logFilePath2 := path.Join(dir, "test_clean.log") + if err = createFile(logFilePath2, true); err != nil { + t.Errorf("create file[%v] err[%v]", logFilePath2, err) + return + } + logFilePath3 := path.Join(dir, "test_clean.log.new") + if err = createFile(logFilePath3, false); err != nil { + t.Errorf("create file[%v] err[%v]", logFilePath3, err) + return + } + + newRaftLogger("/tmp/raft") + time.Sleep(time.Second * 10) + + _, err = os.Stat(logFilePath1) + if !os.IsNotExist(err) { + t.Errorf("expect file[%v] doesn't exist but err is [%v]", logFilePath1, err) + return + } + _, err = os.Stat(logFilePath2) + if err != nil { + t.Errorf("expect file[%v] exists but err is [%v]", logFilePath2, err) + return + } + _, err = os.Stat(logFilePath3) + if err != nil { + t.Errorf("expect file[%v] exists but err is [%v]", logFilePath3, err) + return + } + + os.RemoveAll(dir) +} + +// create file and modify modTime to 7 days ago +func createFile(logFilePath string, modTime bool) (err error) { + _, err = os.Create(logFilePath) + if err != nil { + return + } + info, err := os.Stat(logFilePath) + if err != nil { + return + } + if modTime { + err = os.Chtimes(logFilePath, info.ModTime().AddDate(0, 0, -7), info.ModTime().AddDate(0, 0, -7)) + if err != nil { + return + } + } + return +} diff --git a/vendor/github.com/tiglabs/raft/util/log/log.go b/vendor/github.com/tiglabs/raft/util/log/log.go index d0f47630a..e016944eb 100644 --- a/vendor/github.com/tiglabs/raft/util/log/log.go +++ b/vendor/github.com/tiglabs/raft/util/log/log.go @@ -19,7 +19,10 @@ import ( "fmt" "io" "os" + "path" "runtime" + "sort" + "strings" "sync" "time" ) @@ -34,6 +37,7 @@ const ( LstdFlags = Ldate | Ltime // initial values for the standard logger LogFileNameDateFormat = "2006-01-02" + LogMaxReservedDays = 7 * 24 * time.Hour ) var ( @@ -55,6 +59,20 @@ func newLogWriter(out io.WriteCloser, prefix string, flag int) *logWriter { return &logWriter{out: out, prefix: prefix, flag: flag} } +type RolledFile []os.FileInfo + +func (f RolledFile) Less(i, j int) bool { + return f[i].ModTime().Before(f[j].ModTime()) +} + +func (f RolledFile) Len() int { + return len(f) +} + +func (f RolledFile) Swap(i, j int) { + f[i], f[j] = f[j], f[i] +} + func itoa(buf *[]byte, i int, wid int) { var u uint = uint(i) if u == 0 && wid <= 1 { @@ -237,6 +255,7 @@ func NewLog(dir, module, level string) (*Log, error) { if dir != "" { go lg.checkLogRotation(dir, module) + go lg.checkCleanLog(dir) } go lg.loopMsg() @@ -409,6 +428,41 @@ func (l *Log) checkLogRotation(logDir, module string) { } } +func (l *Log) checkCleanLog(logDir string) { + // handle panic + defer func() { + if r := recover(); r != nil { + fmt.Printf("[Util.Logger]Check clean logger file panic: [%s]\r\n", r) + } + }() + + for { + raftDir, err := os.Open(logDir) + if err != nil { + time.Sleep(time.Second * 60) + continue + } + fInfos, err := raftDir.Readdir(0) + if err != nil || len(fInfos) == 0 { + time.Sleep(time.Second * 60) + continue + } + var needDelFiles RolledFile + for _, info := range fInfos { + if time.Since(info.ModTime()) > LogMaxReservedDays && !strings.HasSuffix(info.Name(), ".log") { + needDelFiles = append(needDelFiles, info) + } + } + sort.Sort(needDelFiles) + for _, info := range needDelFiles { + if err = os.Remove(path.Join(logDir, info.Name())); err != nil { + fmt.Printf("[Util.Logger]Remove logger file[%s] err: [%s]\r\n", info.Name(), err) + } + } + time.Sleep(time.Hour * 24) + } +} + func (l *Log) Debug(format string, v ...interface{}) { if l.IsEnableDebug() { l.Output(3, l.SetPrefix(fmt.Sprintf(format+"\r\n", v...), levels[DebugLevel]), false)