If the directory containing the target log file doesn't exist, try and create the directory first
67 lines
1.3 KiB
Go
67 lines
1.3 KiB
Go
// File wrapper for rotating log files
|
|
// Copied from https://stackoverflow.com/a/28797984
|
|
package logrotate
|
|
|
|
import (
|
|
"os"
|
|
"path"
|
|
"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.
|
|
dir := path.Dir(w.filename)
|
|
_, err = os.Stat(dir)
|
|
if err != nil {
|
|
if err = os.Mkdir(dir, os.ModeDir); err != nil {
|
|
return
|
|
}
|
|
}
|
|
w.fp, err = os.Create(w.filename)
|
|
return
|
|
}
|