You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
1.6 KiB
Go

7 years ago
package writers
import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"sort"
"strings"
"time"
)
// DailyFileWriter create new log for every day
type DailyFileWriter struct {
Name string
MaxCount int
file *os.File
nextDayTime int64
}
// Write implements io.Writer
func (w *DailyFileWriter) Write(p []byte) (n int, err error) {
now := time.Now()
if w.file == nil {
if err = w.openFile(&now); err != nil {
return
}
} else if now.Unix() >= w.nextDayTime {
w.file.Close()
if err = w.openFile(&now); err != nil {
return
}
}
return w.file.Write(p)
}
func (w *DailyFileWriter) openFile(now *time.Time) (err error) {
name := fmt.Sprintf("%s.%s", w.Name, now.Format("20060102"))
// remove symbol link if exist
os.Remove(w.Name)
// create symbol
err = os.Symlink(path.Base(name), w.Name)
if err != nil {
return err
}
w.file, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return err
}
year, month, day := now.Date()
w.nextDayTime = time.Date(year, month, day+1, 0, 0, 0, 0, now.Location()).Unix()
if w.MaxCount > 0 {
go w.cleanFiles()
}
return nil
}
// clean old files
func (w *DailyFileWriter) cleanFiles() {
dir := path.Dir(w.Name)
fileList, err := ioutil.ReadDir(dir)
if err != nil {
return
}
prefix := path.Base(w.Name) + "."
var matches []string
for _, f := range fileList {
if !f.IsDir() && strings.HasPrefix(f.Name(), prefix) {
matches = append(matches, f.Name())
}
}
if len(matches) > w.MaxCount {
sort.Sort(sort.Reverse(sort.StringSlice(matches)))
for _, f := range matches[w.MaxCount:] {
file := filepath.Join(dir, f)
os.Remove(file)
}
}
}