From 602ad9b75a39c0764e643bdb739cffa3f6f6cf83 Mon Sep 17 00:00:00 2001 From: godliness Date: Fri, 1 Feb 2019 18:03:31 +0800 Subject: [PATCH] Fix rotating log makes dfdaemon.log file huge size When the size of dfdaemon.log file large than 20M, the size of log file will continuous growth up. Use Mmap to copy the file which need be truncated. Related to issue: https://github.com/dragonflyoss/Dragonfly/issues/364 Signed-off-by: godliness --- dfdaemon/initializer/initializer.go | 55 +++++++++++++++++------------ 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/dfdaemon/initializer/initializer.go b/dfdaemon/initializer/initializer.go index b6a6bcb15..62a7b3541 100644 --- a/dfdaemon/initializer/initializer.go +++ b/dfdaemon/initializer/initializer.go @@ -18,7 +18,6 @@ package initializer import ( "fmt" - "io" "io/ioutil" "os" "os/exec" @@ -102,32 +101,35 @@ func cleanLocalRepo(options *options.Options) { } // rotateLog truncates the logs file by a certain amount bytes. -func rotateLog(logFile *os.File, logFilePath string) { +func rotateLog(logFile *os.File) error { + stat, err := logFile.Stat() + if err != nil { + return err + } logSizeLimit := int64(20 * 1024 * 1024) - for { - time.Sleep(time.Second * 60) - stat, err := os.Stat(logFilePath) + // if it exceeds the 20MB limitation + if stat.Size() > logSizeLimit { + log.SetOutput(ioutil.Discard) + // make sure set the output of log back to logFile when error be raised. + defer log.SetOutput(logFile) + logFile.Sync() + truncateSize := logSizeLimit/2 - 1 + mem, err := syscall.Mmap(int(logFile.Fd()), 0, int(stat.Size()), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) if err != nil { - log.Errorf("failed to stat %s: %s", logFilePath, err) - continue + return err } - // if it exceeds the 20MB limitation - if stat.Size() > logSizeLimit { - log.SetOutput(ioutil.Discard) - logFile.Sync() - if transFile, err := os.Open(logFilePath); err == nil { - // move the pointer to be (end - 10MB) - transFile.Seek(-10*1024*1024, 2) - // move the pointer to head - logFile.Seek(0, 0) - count, _ := io.Copy(logFile, transFile) - logFile.Truncate(count) - log.SetOutput(logFile) - transFile.Close() - } + copy(mem[0:], mem[truncateSize:]) + if err := syscall.Munmap(mem); err != nil { + return err + } + if err := logFile.Truncate(stat.Size() - truncateSize); err != nil { + return err + } + if _, err := logFile.Seek(truncateSize, 0); err != nil { + return err } } - + return nil } func initLogger() { @@ -148,7 +150,14 @@ func initLogger() { if logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644); err == nil { logFile.Seek(0, 2) log.SetOutput(logFile) - go rotateLog(logFile, logFilePath) + go func(logFile *os.File) { + ticker := time.NewTicker(60 * time.Second) + for range ticker.C { + if err := rotateLog(logFile); err != nil { + log.Errorf("failed to rotate log %s: %v", logFile.Name(), err) + } + } + }(logFile) } }