package logmanager
import ( "compress/gzip" "io" "os" "path/filepath" "time" "github.com/rs/zerolog" )
type LogManager struct { currentFile *os.File basePath string maxSize int64 maxBackups int maxAge time.Duration }
func NewLogManager(basePath string, maxSize int64, maxBackups int, maxAge time.Duration) *LogManager { return &LogManager{ basePath: basePath, maxSize: maxSize, maxBackups: maxBackups, maxAge: maxAge, } }
func (lm *LogManager) Write(p []byte) (n int, err error) { if lm.currentFile == nil || lm.needRotate() { if err := lm.rotate(); err != nil { return 0, err } } return lm.currentFile.Write(p) }
func (lm *LogManager) needRotate() bool { if lm.currentFile == nil { return true } info, err := lm.currentFile.Stat() if err != nil { return true } return info.Size() >= lm.maxSize }
func (lm *LogManager) rotate() error { if lm.currentFile != nil { if err := lm.currentFile.Close(); err != nil { return err } go lm.compressFile(lm.currentFile.Name()) } timestamp := time.Now().Format("2006-01-02_15-04-05") newPath := filepath.Join(lm.basePath, "app_"+timestamp+".log") file, err := os.OpenFile(newPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return err } lm.currentFile = file go lm.cleanupOldLogs() return nil }
func (lm *LogManager) compressFile(path string) { src, err := os.Open(path) if err != nil { return } defer src.Close() dstPath := path + ".gz" dst, err := os.Create(dstPath) if err != nil { return } defer dst.Close() gz := gzip.NewWriter(dst) defer gz.Close() if _, err := io.Copy(gz, src); err != nil { return } os.Remove(path) }
func (lm *LogManager) cleanupOldLogs() { files, err := filepath.Glob(filepath.Join(lm.basePath, "app_*.log.gz")) if err != nil { return } sort.Slice(files, func(i, j int) bool { infoI, _ := os.Stat(files[i]) infoJ, _ := os.Stat(files[j]) return infoI.ModTime().After(infoJ.ModTime()) }) if len(files) > lm.maxBackups { for _, file := range files[lm.maxBackups:] { os.Remove(file) } } cutoff := time.Now().Add(-lm.maxAge) for _, file := range files { info, err := os.Stat(file) if err != nil { continue } if info.ModTime().Before(cutoff) { os.Remove(file) } } }
func setupCustomLogManager() zerolog.Logger { logManager := NewLogManager("/var/log/app", 100*1024*1024, 10, 30*24*time.Hour) logger := zerolog.New(logManager).With().Timestamp().Logger() return logger }
|