Commit 002dcaab authored by astaxie's avatar astaxie

Merge pull request #1880 from JessonChan/log_rotate_fix

Log rotate fix
parents 314a447d abaa1bbc
...@@ -47,6 +47,7 @@ type fileLogWriter struct { ...@@ -47,6 +47,7 @@ type fileLogWriter struct {
Daily bool `json:"daily"` Daily bool `json:"daily"`
MaxDays int64 `json:"maxdays"` MaxDays int64 `json:"maxdays"`
dailyOpenDate int dailyOpenDate int
dailyOpenTime time.Time
Rotate bool `json:"rotate"` Rotate bool `json:"rotate"`
...@@ -163,7 +164,8 @@ func (w *fileLogWriter) initFd() error { ...@@ -163,7 +164,8 @@ func (w *fileLogWriter) initFd() error {
return fmt.Errorf("get stat err: %s\n", err) return fmt.Errorf("get stat err: %s\n", err)
} }
w.maxSizeCurSize = int(fInfo.Size()) w.maxSizeCurSize = int(fInfo.Size())
w.dailyOpenDate = time.Now().Day() w.dailyOpenTime = time.Now()
w.dailyOpenDate = w.dailyOpenTime.Day()
w.maxLinesCurLines = 0 w.maxLinesCurLines = 0
if fInfo.Size() > 0 { if fInfo.Size() > 0 {
count, err := w.lines() count, err := w.lines()
...@@ -205,22 +207,29 @@ func (w *fileLogWriter) lines() (int, error) { ...@@ -205,22 +207,29 @@ func (w *fileLogWriter) lines() (int, error) {
// DoRotate means it need to write file in new file. // DoRotate means it need to write file in new file.
// new file name like xx.2013-01-01.log (daily) or xx.001.log (by line or size) // new file name like xx.2013-01-01.log (daily) or xx.001.log (by line or size)
func (w *fileLogWriter) doRotate(logTime time.Time) error { func (w *fileLogWriter) doRotate(logTime time.Time) error {
_, err := os.Lstat(w.Filename)
if err != nil {
return err
}
// file exists // file exists
// Find the next available number // Find the next available number
num := 1 num := 1
fName := "" fName := ""
_, err := os.Lstat(w.Filename)
if err != nil {
//even if the file is not exist or other ,we should RESTART the logger
goto RESTART_LOGGER
}
if w.MaxLines > 0 || w.MaxSize > 0 { if w.MaxLines > 0 || w.MaxSize > 0 {
for ; err == nil && num <= 999; num++ { for ; err == nil && num <= 999; num++ {
fName = w.fileNameOnly + fmt.Sprintf(".%s.%03d%s", logTime.Format("2006-01-02"), num, w.suffix) fName = w.fileNameOnly + fmt.Sprintf(".%s.%03d%s", logTime.Format("2006-01-02"), num, w.suffix)
_, err = os.Lstat(fName) _, err = os.Lstat(fName)
} }
} else { } else {
fName = fmt.Sprintf("%s.%s%s", w.fileNameOnly, logTime.Format("2006-01-02"), w.suffix) fName = fmt.Sprintf("%s.%s%s", w.fileNameOnly, w.dailyOpenTime.Format("2006-01-02"), w.suffix)
_, err = os.Lstat(fName) _, err = os.Lstat(fName)
for ; err == nil && num <= 999; num++ {
fName = w.fileNameOnly + fmt.Sprintf(".%s.%03d%s", w.dailyOpenTime.Format("2006-01-02"), num, w.suffix)
_, err = os.Lstat(fName)
}
} }
// return error if the last file checked still existed // return error if the last file checked still existed
if err == nil { if err == nil {
...@@ -232,16 +241,18 @@ func (w *fileLogWriter) doRotate(logTime time.Time) error { ...@@ -232,16 +241,18 @@ func (w *fileLogWriter) doRotate(logTime time.Time) error {
// Rename the file to its new found name // Rename the file to its new found name
// even if occurs error,we MUST guarantee to restart new logger // even if occurs error,we MUST guarantee to restart new logger
renameErr := os.Rename(w.Filename, fName) err = os.Rename(w.Filename, fName)
// re-start logger // re-start logger
RESTART_LOGGER:
startLoggerErr := w.startLogger() startLoggerErr := w.startLogger()
go w.deleteOldLog() go w.deleteOldLog()
if startLoggerErr != nil { if startLoggerErr != nil {
return fmt.Errorf("Rotate StartLogger: %s\n", startLoggerErr) return fmt.Errorf("Rotate StartLogger: %s\n", startLoggerErr)
} }
if renameErr != nil { if err != nil {
return fmt.Errorf("Rotate: %s\n", renameErr) return fmt.Errorf("Rotate: %s\n", err)
} }
return nil return nil
...@@ -256,6 +267,10 @@ func (w *fileLogWriter) deleteOldLog() { ...@@ -256,6 +267,10 @@ func (w *fileLogWriter) deleteOldLog() {
} }
}() }()
if info == nil {
return
}
if !info.IsDir() && info.ModTime().Add(24*time.Hour*time.Duration(w.MaxDays)).Before(time.Now()) { if !info.IsDir() && info.ModTime().Add(24*time.Hour*time.Duration(w.MaxDays)).Before(time.Now()) {
if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) && if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
strings.HasSuffix(filepath.Base(path), w.suffix) { strings.HasSuffix(filepath.Base(path), w.suffix) {
......
...@@ -89,7 +89,7 @@ func TestFile2(t *testing.T) { ...@@ -89,7 +89,7 @@ func TestFile2(t *testing.T) {
os.Remove("test2.log") os.Remove("test2.log")
} }
func TestFileRotate(t *testing.T) { func TestFileRotate_01(t *testing.T) {
log := NewLogger(10000) log := NewLogger(10000)
log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`) log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`)
log.Debug("debug") log.Debug("debug")
...@@ -110,6 +110,43 @@ func TestFileRotate(t *testing.T) { ...@@ -110,6 +110,43 @@ func TestFileRotate(t *testing.T) {
os.Remove("test3.log") os.Remove("test3.log")
} }
func TestFileRotate_02(t *testing.T) {
fn1 := "rotate_day.log"
fn2 := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".log"
testFileRotate(t, fn1, fn2)
}
func TestFileRotate_03(t *testing.T) {
fn1 := "rotate_day.log"
fn := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".log"
os.Create(fn)
fn2 := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".001.log"
testFileRotate(t, fn1, fn2)
os.Remove(fn)
}
func testFileRotate(t *testing.T, fn1, fn2 string) {
fw := &fileLogWriter{
Daily: true,
MaxDays: 7,
Rotate: true,
Level: LevelTrace,
Perm: 0660,
}
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
fw.dailyOpenDate = fw.dailyOpenTime.Day()
fw.WriteMsg(time.Now(), "this is a msg for test", LevelDebug)
for _, file := range []string{fn1, fn2} {
_, err := os.Stat(file)
if err != nil {
t.FailNow()
}
os.Remove(file)
}
}
func exists(path string) (bool, error) { func exists(path string) (bool, error) {
_, err := os.Stat(path) _, err := os.Stat(path)
if err == nil { if err == nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment