diff --git a/os/glog/glog_logger.go b/os/glog/glog_logger.go index 25f82e16d..8455fa9d1 100644 --- a/os/glog/glog_logger.go +++ b/os/glog/glog_logger.go @@ -27,7 +27,6 @@ import ( "github.com/gogf/gf/v2/os/gfpool" "github.com/gogf/gf/v2/os/gmlock" "github.com/gogf/gf/v2/os/gtime" - "github.com/gogf/gf/v2/os/gtimer" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/util/gconv" ) @@ -100,7 +99,7 @@ func (l *Logger) print(ctx context.Context, level int, stack string, values ...i // It just initializes once for each logger. if l.config.RotateSize > 0 || l.config.RotateExpire > 0 { if !l.config.rotatedHandlerInitialized.Val() && l.config.rotatedHandlerInitialized.Cas(false, true) { - gtimer.AddOnce(context.Background(), l.config.RotateCheckInterval, l.rotateChecksTimely) + l.rotateChecksTimely(ctx) intlog.Printf(ctx, "logger rotation initialized: every %s", l.config.RotateCheckInterval.String()) } } diff --git a/os/glog/glog_logger_rotate.go b/os/glog/glog_logger_rotate.go index b467fb914..6090e517a 100644 --- a/os/glog/glog_logger_rotate.go +++ b/os/glog/glog_logger_rotate.go @@ -10,6 +10,7 @@ import ( "context" "fmt" "runtime" + "strings" "time" "github.com/gogf/gf/v2/container/garray" @@ -137,6 +138,11 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { intlog.Errorf(ctx, `%+v`, err) } intlog.Printf(ctx, "logging rotation start checks: %+v", files) + // get file name regex pattern + // access-{y-m-d}-test.log => access-$-test.log => access-\$-test\.log => access-(.+?)-test\.log + fileNameRegexPattern, _ := gregex.ReplaceString(`{.+?}`, "$", l.config.File) + fileNameRegexPattern = gregex.Quote(fileNameRegexPattern) + fileNameRegexPattern = strings.ReplaceAll(fileNameRegexPattern, "\\$", "(.+?)") // ============================================================= // Rotation of expired file checks. // ============================================================= @@ -147,7 +153,12 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { expireRotated bool ) for _, file := range files { - if gfile.ExtName(file) == "gz" { + // ignore backup file + if gregex.IsMatchString(`.+\.\d{20}\.log`, gfile.Basename(file)) { + continue + } + // ignore not matching file + if !gregex.IsMatchString(fileNameRegexPattern, file) { continue } mtime = gfile.MTime(file) @@ -159,19 +170,16 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { return } defer gmlock.Unlock(memoryLockFileKey) - - fp := l.getOpenedFilePointer(ctx, file) - if fp == nil { - intlog.Errorf(ctx, `got nil file pointer for: %s`, file) - return - } - if runtime.GOOS == "windows" { + fp := l.getOpenedFilePointer(ctx, file) + if fp == nil { + intlog.Errorf(ctx, `got nil file pointer for: %s`, file) + return + } if err := fp.Close(true); err != nil { intlog.Errorf(ctx, `%+v`, err) } } - expireRotated = true intlog.Printf( ctx, @@ -203,6 +211,11 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { if gfile.ExtName(file) == "gz" { continue } + // ignore not matching file + originalLoggingFilePath, _ := gregex.ReplaceString(`\.\d{20}`, "", file) + if !gregex.IsMatchString(fileNameRegexPattern, originalLoggingFilePath) { + continue + } // Eg: // access.20200326101301899002.log if gregex.IsMatchString(`.+\.\d{20}\.log`, gfile.Basename(file)) { @@ -233,42 +246,37 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { // ============================================================= // Backups count limitation and expiration checks. // ============================================================= - var ( - backupFilesMap = make(map[string]*garray.SortedArray) - originalLoggingFilePath string - ) + backupFiles := garray.NewSortedArray(func(a, b interface{}) int { + // Sorted by rotated/backup file mtime. + // The older rotated/backup file is put in the head of array. + var ( + file1 = a.(string) + file2 = b.(string) + result = gfile.MTimestampMilli(file1) - gfile.MTimestampMilli(file2) + ) + if result <= 0 { + return -1 + } + return 1 + }) if l.config.RotateBackupLimit > 0 || l.config.RotateBackupExpire > 0 { for _, file := range files { - originalLoggingFilePath, _ = gregex.ReplaceString(`\.\d{20}`, "", file) - if backupFilesMap[originalLoggingFilePath] == nil { - backupFilesMap[originalLoggingFilePath] = garray.NewSortedArray(func(a, b interface{}) int { - // Sorted by rotated/backup file mtime. - // The older rotated/backup file is put in the head of array. - var ( - file1 = a.(string) - file2 = b.(string) - result = gfile.MTimestampMilli(file1) - gfile.MTimestampMilli(file2) - ) - if result <= 0 { - return -1 - } - return 1 - }) + // ignore not matching file + originalLoggingFilePath, _ := gregex.ReplaceString(`\.\d{20}`, "", file) + if !gregex.IsMatchString(fileNameRegexPattern, originalLoggingFilePath) { + continue } - // Check if this file a rotated/backup file. if gregex.IsMatchString(`.+\.\d{20}\.log`, gfile.Basename(file)) { - backupFilesMap[originalLoggingFilePath].Add(file) + backupFiles.Add(file) } } - intlog.Printf(ctx, `calculated backup files map: %+v`, backupFilesMap) - for _, array := range backupFilesMap { - diff := array.Len() - l.config.RotateBackupLimit - for i := 0; i < diff; i++ { - path, _ := array.PopLeft() - intlog.Printf(ctx, `remove exceeded backup limit file: %s`, path) - if err := gfile.Remove(path.(string)); err != nil { - intlog.Errorf(ctx, `%+v`, err) - } + intlog.Printf(ctx, `calculated backup files array: %+v`, backupFiles) + diff := backupFiles.Len() - l.config.RotateBackupLimit + for i := 0; i < diff; i++ { + path, _ := backupFiles.PopLeft() + intlog.Printf(ctx, `remove exceeded backup limit file: %s`, path) + if err := gfile.Remove(path.(string)); err != nil { + intlog.Errorf(ctx, `%+v`, err) } } // Backups expiration checking. @@ -277,26 +285,24 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { mtime time.Time subDuration time.Duration ) - for _, array := range backupFilesMap { - array.Iterator(func(_ int, v interface{}) bool { - path := v.(string) - mtime = gfile.MTime(path) - subDuration = now.Sub(mtime) - if subDuration > l.config.RotateBackupExpire { - intlog.Printf( - ctx, - `%v - %v = %v > %v, remove expired backup file: %s`, - now, mtime, subDuration, l.config.RotateBackupExpire, path, - ) - if err := gfile.Remove(path); err != nil { - intlog.Errorf(ctx, `%+v`, err) - } - return true - } else { - return false + backupFiles.Iterator(func(_ int, v interface{}) bool { + path := v.(string) + mtime = gfile.MTime(path) + subDuration = now.Sub(mtime) + if subDuration > l.config.RotateBackupExpire { + intlog.Printf( + ctx, + `%v - %v = %v > %v, remove expired backup file: %s`, + now, mtime, subDuration, l.config.RotateBackupExpire, path, + ) + if err := gfile.Remove(path); err != nil { + intlog.Errorf(ctx, `%+v`, err) } - }) - } + return true + } else { + return false + } + }) } } }