From eedc7b9dc15055b8a75274e73b3a1fbd8f6eed69 Mon Sep 17 00:00:00 2001 From: mstar Date: Mon, 24 Mar 2025 08:23:36 +0100 Subject: [PATCH] Add log rotator --- logrotate/logrotate.go | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 logrotate/logrotate.go diff --git a/logrotate/logrotate.go b/logrotate/logrotate.go new file mode 100644 index 0000000..e569dad --- /dev/null +++ b/logrotate/logrotate.go @@ -0,0 +1,59 @@ +// File wrapper for rotating log files +// Copied from https://stackoverflow.com/a/28797984 +package logrotate + +import ( + "os" + "sync" + "time" +) + +type RotateWriter struct { + lock sync.Mutex + filename string // should be set to the actual filename + fp *os.File +} + +// Make a new RotateWriter. Return nil if error occurs during setup. +func New(filename string) *RotateWriter { + w := &RotateWriter{filename: filename} + err := w.Rotate() + if err != nil { + return nil + } + return w +} + +// Write satisfies the io.Writer interface. +func (w *RotateWriter) Write(output []byte) (int, error) { + w.lock.Lock() + defer w.lock.Unlock() + return w.fp.Write(output) +} + +// Perform the actual act of rotating and reopening file. +func (w *RotateWriter) Rotate() (err error) { + w.lock.Lock() + defer w.lock.Unlock() + + // Close existing file if open + if w.fp != nil { + err = w.fp.Close() + w.fp = nil + if err != nil { + return + } + } + // Rename dest file if it already exists + _, err = os.Stat(w.filename) + if err == nil { + err = os.Rename(w.filename, w.filename+"."+time.Now().Format(time.RFC3339)) + if err != nil { + return + } + } + + // Create a file. + w.fp, err = os.Create(w.filename) + return +}