goutils/logrotate/logrotate.go
mstar afcc54c831
BREAKING CHANGE: Remodelled logging setup
- other.ConfigureLoggingFromCliArgs has been renamed to
  other.ConfigureLogging
- The -logfile cli argument has been removed and replaced with an
  argument to other.ConfigureLogging. This argument takes a pointer to a
  string or nil. If it's a valid pointer, it's used just like the
  -logfile cli flag before
- The logfile, if requested via the previously mentioned parameter, can
  now be rotated by calling the returned function. If no logfile is
  specified, the returned function does nothing
2025-03-24 08:39:04 +01:00

59 lines
1.2 KiB
Go

// 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, error) {
w := &RotateWriter{filename: filename}
err := w.Rotate()
if err != nil {
return nil, err
}
return w, nil
}
// 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
}