1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-26 07:11:29 +00:00

remove the lock writer

This commit is contained in:
JessonChan 2016-01-13 09:21:55 +08:00
parent 58730e3528
commit 7663d50c97

View File

@ -30,10 +30,12 @@ import (
// fileLogWriter implements LoggerInterface. // fileLogWriter implements LoggerInterface.
// It writes messages by lines limit, file size limit, or time frequency. // It writes messages by lines limit, file size limit, or time frequency.
type fileLogWriter struct { type fileLogWriter struct {
*MuxWriter sync.Mutex // write log order by order and atomic incr maxLinesCurLines and maxSizeCurSize
// The opened file // The opened file
Filename string `json:"filename"` Filename string `json:"filename"`
fileWriter *os.File
// Rotate at line
MaxLines int `json:"maxlines"` MaxLines int `json:"maxlines"`
maxLinesCurLines int maxLinesCurLines int
@ -48,47 +50,22 @@ type fileLogWriter struct {
Rotate bool `json:"rotate"` Rotate bool `json:"rotate"`
startLock sync.Mutex // atomic incr maxLinesCurLines and maxSizeCurSize
Level int `json:"level"` Level int `json:"level"`
Perm os.FileMode `json:"perm"` Perm os.FileMode `json:"perm"`
} }
// MuxWriter is an *os.File writer with locker,lock write when rotate
type MuxWriter struct {
sync.Mutex
fileWriter *os.File
}
// Write to os.File.
func (mw *MuxWriter) Write(b []byte) (int, error) {
mw.Lock()
n, e := mw.fileWriter.Write(b)
mw.Unlock()
return n, e
}
// SetFileWriter set os.File in writer.
func (mw *MuxWriter) SetFileWriter(fd *os.File) {
if mw.fileWriter != nil {
mw.fileWriter.Close()
}
mw.fileWriter = fd
}
// NewFileWriter create a FileLogWriter returning as LoggerInterface. // NewFileWriter create a FileLogWriter returning as LoggerInterface.
func newFileWriter() Logger { func newFileWriter() Logger {
w := &fileLogWriter{ w := &fileLogWriter{
Filename: "", Filename: "",
MaxLines: 1000000, MaxLines: 1000000,
MaxSize: 1 << 28, //256 MB MaxSize: 1 << 28, //256 MB
Daily: true, Daily: true,
MaxDays: 7, MaxDays: 7,
Rotate: true, Rotate: true,
Level: LevelTrace, Level: LevelTrace,
Perm: 0660, Perm: 0660,
MuxWriter: new(MuxWriter),
} }
return w return w
} }
@ -122,24 +99,18 @@ func (w *fileLogWriter) startLogger() error {
if err != nil { if err != nil {
return err return err
} }
w.SetFileWriter(file) if w.fileWriter != nil {
w.fileWriter.Close()
}
w.fileWriter = file
return w.initFd() return w.initFd()
} }
func (w *fileLogWriter) doCheck(size int) { func (w *fileLogWriter) needRotate(size int, day int) bool {
w.startLock.Lock() return (w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) ||
if w.Rotate { (w.MaxSize > 0 && w.maxSizeCurSize >= w.MaxSize) ||
if (w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) || (w.Daily && day != w.dailyOpenDate)
(w.MaxSize > 0 && w.maxSizeCurSize >= w.MaxSize) ||
(w.Daily && time.Now().Day() != w.dailyOpenDate) {
if err := w.DoRotate(); err != nil {
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
}
}
}
w.maxLinesCurLines++
w.maxSizeCurSize += size
w.startLock.Unlock()
} }
// WriteMsg write logger message into file. // WriteMsg write logger message into file.
@ -185,11 +156,29 @@ func (w *fileLogWriter) WriteMsg(msg string, level int) error {
t = s / 10 t = s / 10
buf[17] = byte('0' + t) buf[17] = byte('0' + t)
buf[18] = byte('0' + s - t*10) buf[18] = byte('0' + s - t*10)
buf[18] = ' ' buf[19] = ' '
msg = string(buf[0:]) + msg + "\n" msg = string(buf[0:]) + msg + "\n"
w.doCheck(len(msg)) if w.Rotate {
_, err := w.Write([]byte(msg)) if w.needRotate(len(msg), d) {
w.Lock()
if w.needRotate(len(msg), d) {
if err := w.doRotate(); err != nil {
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
}
}
w.Unlock()
}
}
w.Lock()
_, err := w.fileWriter.Write([]byte(msg))
if err == nil {
w.maxLinesCurLines++
w.maxSizeCurSize += len(msg)
}
w.Unlock()
return err return err
} }
@ -247,7 +236,7 @@ func (w *fileLogWriter) lines() (int, error) {
// DoRotate means it need to write file in new file. // DoRotate means it need to write file in new file.
// new file name like xx.2013-01-01.2.log // new file name like xx.2013-01-01.2.log
func (w *fileLogWriter) DoRotate() error { func (w *fileLogWriter) doRotate() error {
_, err := os.Lstat(w.Filename) _, err := os.Lstat(w.Filename)
if err == nil { if err == nil {
// file exists // file exists
@ -268,27 +257,22 @@ func (w *fileLogWriter) DoRotate() error {
return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.Filename) return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.Filename)
} }
// block Logger's io.Writer // close fileWriter before rename
w.Lock() w.fileWriter.Close()
defer w.Unlock()
fd := w.fileWriter
fd.Close()
// close fd before rename
// Rename the file to its new found name // Rename the file to its new found name
err = os.Rename(w.Filename, fName) // even if occurs error,we MUST guarantee to restart new logger
if err != nil { renameErr := os.Rename(w.Filename, fName)
return fmt.Errorf("Rotate: %s\n", err)
}
// re-start logger // re-start logger
err = w.startLogger() startLoggerErr := w.startLogger()
if err != nil {
return fmt.Errorf("Rotate StartLogger: %s\n", err)
}
go w.deleteOldLog() go w.deleteOldLog()
if startLoggerErr != nil {
return fmt.Errorf("Rotate StartLogger: %s\n", startLoggerErr)
}
if renameErr != nil {
return fmt.Errorf("Rotate: %s\n", renameErr)
}
} }
return nil return nil