81 lines
1.2 KiB
Go
81 lines
1.2 KiB
Go
package logging
|
|
|
|
import (
|
|
"compress/gzip"
|
|
"io"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// implements io.Writer interface
|
|
type LogRotateWriter struct {
|
|
mu sync.Mutex
|
|
fd *os.File
|
|
filename string
|
|
}
|
|
|
|
func NewRotableLogger(filename string) (*LogRotateWriter, error) {
|
|
fd, err := os.Create(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
w := &LogRotateWriter{filename: filename, fd: fd}
|
|
return w, nil
|
|
}
|
|
|
|
func (w *LogRotateWriter) Write(b []byte) (int, error) {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
return w.fd.Write(b)
|
|
}
|
|
|
|
func (w *LogRotateWriter) Rotate() error {
|
|
var err error
|
|
w.mu.Lock()
|
|
|
|
gzFile, err := os.Create(w.filename + "." + time.Now().Format(time.RFC3339) + ".gz")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
data, err := io.ReadAll(w.fd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer func() {
|
|
w.mu.Unlock()
|
|
w.gzipLog(gzFile, &data)
|
|
}()
|
|
|
|
_, err = os.Stat(w.filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if w.fd != nil {
|
|
err = w.fd.Close()
|
|
w.fd = nil
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
err = os.Remove(w.filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
w.fd, err = os.Create(w.filename)
|
|
return err
|
|
}
|
|
|
|
func (w *LogRotateWriter) gzipLog(wr io.Writer, data *[]byte) error {
|
|
if _, err := gzip.NewWriter(wr).Write(*data); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|