From e32e3a759c4c06bbfa0f30acacde90426f1edf81 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 17:46:10 +0800 Subject: [PATCH 01/17] console type no need to bench --- logs/console_test.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/logs/console_test.go b/logs/console_test.go index 2fad7241..c4bb1da2 100644 --- a/logs/console_test.go +++ b/logs/console_test.go @@ -43,11 +43,3 @@ func TestConsole(t *testing.T) { testConsoleCalls(log2) } -func BenchmarkConsole(b *testing.B) { - log := NewLogger(10000) - log.EnableFuncCallDepth(true) - log.SetLogger("console", "") - for i := 0; i < b.N; i++ { - log.Debug("debug") - } -} From c9b890b10ee0949dc2e70997faa300774f914edf Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 17:59:23 +0800 Subject: [PATCH 02/17] add asynchronous benchmark --- logs/file_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/logs/file_test.go b/logs/file_test.go index 97260f12..f7929942 100644 --- a/logs/file_test.go +++ b/logs/file_test.go @@ -131,3 +131,13 @@ func BenchmarkFile(b *testing.B) { } os.Remove("test4.log") } + +func BenchmarkAsynchronousFile(b *testing.B) { + log := NewLogger(100000) + log.SetLogger("file", `{"filename":"test4.log"}`) + log.Async() + for i := 0; i < b.N; i++ { + log.Debug("debug") + } + os.Remove("test4.log") +} From 2479e61db99f753104b4506d47733975c6fbcedd Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 19:09:00 +0800 Subject: [PATCH 03/17] add asynchronous and call depth benchmark --- logs/file_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/logs/file_test.go b/logs/file_test.go index f7929942..d03d3ca5 100644 --- a/logs/file_test.go +++ b/logs/file_test.go @@ -141,3 +141,26 @@ func BenchmarkAsynchronousFile(b *testing.B) { } os.Remove("test4.log") } + +func BenchmarkCallDepthFile(b *testing.B) { + log := NewLogger(100000) + log.SetLogger("file", `{"filename":"test4.log"}`) + log.EnableFuncCallDepth(true) + log.SetLogFuncCallDepth(2) + for i := 0; i < b.N; i++ { + log.Debug("debug") + } + os.Remove("test4.log") +} + +func BenchmarkAsynchronousCallDepthFile(b *testing.B) { + log := NewLogger(100000) + log.SetLogger("file", `{"filename":"test4.log"}`) + log.EnableFuncCallDepth(true) + log.SetLogFuncCallDepth(2) + log.Async() + for i := 0; i < b.N; i++ { + log.Debug("debug") + } + os.Remove("test4.log") +} From 9507e59c2f9155045d58bb2e8e40572f621f4b2f Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 19:10:08 +0800 Subject: [PATCH 04/17] camel name fixed --- logs/file.go | 72 ++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/logs/file.go b/logs/file.go index 9596258c..abc700cf 100644 --- a/logs/file.go +++ b/logs/file.go @@ -32,29 +32,29 @@ import ( // It writes messages by lines limit, file size limit, or time frequency. type fileLogWriter struct { *log.Logger - mw *MuxWriter + mw *MuxWriter // The opened file - Filename string `json:"filename"` + Filename string `json:"filename"` - Maxlines int `json:"maxlines"` - maxlinesCurlines int + MaxLines int `json:"maxlines"` + maxLinesCurLines int // Rotate at size - Maxsize int `json:"maxsize"` - maxsizeCursize int + MaxSize int `json:"maxsize"` + maxSizeCurSize int // Rotate daily - Daily bool `json:"daily"` - Maxdays int64 `json:"maxdays"` - dailyOpendate int + Daily bool `json:"daily"` + MaxDays int64 `json:"maxdays"` + dailyOpenDate int - Rotate bool `json:"rotate"` + Rotate bool `json:"rotate"` - startLock sync.Mutex // Only one log can write to the file + startLock sync.Mutex // Only one log can write to the file - 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. @@ -63,7 +63,7 @@ type MuxWriter struct { fd *os.File } -// write to os.File. +// Write to os.File. func (l *MuxWriter) Write(b []byte) (int, error) { l.Lock() defer l.Unlock() @@ -82,10 +82,10 @@ func (l *MuxWriter) SetFd(fd *os.File) { func newFileWriter() Logger { w := &fileLogWriter{ Filename: "", - Maxlines: 1000000, - Maxsize: 1 << 28, //256 MB + MaxLines: 1000000, + MaxSize: 1 << 28, //256 MB Daily: true, - Maxdays: 7, + MaxDays: 7, Rotate: true, Level: LevelTrace, Perm: 0660, @@ -98,18 +98,18 @@ func newFileWriter() Logger { } // Init file logger with json config. -// jsonconfig like: +// jsonConfig like: // { // "filename":"logs/beego.log", -// "maxlines":10000, +// "maxLines":10000, // "maxsize":1<<30, // "daily":true, -// "maxdays":15, +// "maxDays":15, // "rotate":true, -// "perm":0600 +// "perm":0600 // } -func (w *fileLogWriter) Init(jsonconfig string) error { - err := json.Unmarshal([]byte(jsonconfig), w) +func (w *fileLogWriter) Init(jsonConfig string) error { + err := json.Unmarshal([]byte(jsonConfig), w) if err != nil { return err } @@ -130,19 +130,19 @@ func (w *fileLogWriter) startLogger() error { return w.initFd() } -func (w *fileLogWriter) docheck(size int) { +func (w *fileLogWriter) doCheck(size int) { w.startLock.Lock() defer w.startLock.Unlock() - if w.Rotate && ((w.Maxlines > 0 && w.maxlinesCurlines >= w.Maxlines) || - (w.Maxsize > 0 && w.maxsizeCursize >= w.Maxsize) || - (w.Daily && time.Now().Day() != w.dailyOpendate)) { + if w.Rotate && ((w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) || + (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) return } } - w.maxlinesCurlines++ - w.maxsizeCursize += size + w.maxLinesCurLines++ + w.maxSizeCurSize += size } // WriteMsg write logger message into file. @@ -151,7 +151,7 @@ func (w *fileLogWriter) WriteMsg(msg string, level int) error { return nil } n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] " - w.docheck(n) + w.doCheck(n) w.Logger.Println(msg) return nil } @@ -168,15 +168,15 @@ func (w *fileLogWriter) initFd() error { if err != nil { return fmt.Errorf("get stat err: %s\n", err) } - w.maxsizeCursize = int(finfo.Size()) - w.dailyOpendate = time.Now().Day() - w.maxlinesCurlines = 0 + w.maxSizeCurSize = int(finfo.Size()) + w.dailyOpenDate = time.Now().Day() + w.maxLinesCurLines = 0 if finfo.Size() > 0 { count, err := w.lines() if err != nil { return err } - w.maxlinesCurlines = count + w.maxLinesCurLines = count } return nil } @@ -266,7 +266,7 @@ func (w *fileLogWriter) deleteOldLog() { } }() - if !info.IsDir() && info.ModTime().Unix() < (time.Now().Unix()-60*60*24*w.Maxdays) { + if !info.IsDir() && info.ModTime().Unix() < (time.Now().Unix()-60*60*24*w.MaxDays) { if strings.HasPrefix(filepath.Base(path), filepath.Base(w.Filename)) { os.Remove(path) } @@ -275,7 +275,7 @@ func (w *fileLogWriter) deleteOldLog() { }) } -// Destroy close the file desciption, close file writer. +// Destroy close the file description, close file writer. func (w *fileLogWriter) Destroy() { w.mw.fd.Close() } From 5511e03b5225ae1a203b02154ffb98638680e8b8 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 19:25:33 +0800 Subject: [PATCH 05/17] embedding file writer --- logs/file.go | 67 ++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/logs/file.go b/logs/file.go index abc700cf..193a7cc6 100644 --- a/logs/file.go +++ b/logs/file.go @@ -32,32 +32,32 @@ import ( // It writes messages by lines limit, file size limit, or time frequency. type fileLogWriter struct { *log.Logger - mw *MuxWriter + *MuxWriter // The opened file - Filename string `json:"filename"` + Filename string `json:"filename"` MaxLines int `json:"maxlines"` maxLinesCurLines int // Rotate at size - MaxSize int `json:"maxsize"` - maxSizeCurSize int + MaxSize int `json:"maxsize"` + maxSizeCurSize int // Rotate daily - Daily bool `json:"daily"` - MaxDays int64 `json:"maxdays"` - dailyOpenDate int + Daily bool `json:"daily"` + MaxDays int64 `json:"maxdays"` + dailyOpenDate int - Rotate bool `json:"rotate"` + Rotate bool `json:"rotate"` - startLock sync.Mutex // Only one log can write to the file + startLock sync.Mutex // Only one log can write to the file - 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. +// MuxWriter is an *os.File writer with locker,lock write when rotate type MuxWriter struct { sync.Mutex fd *os.File @@ -81,19 +81,18 @@ func (l *MuxWriter) SetFd(fd *os.File) { // NewFileWriter create a FileLogWriter returning as LoggerInterface. func newFileWriter() Logger { w := &fileLogWriter{ - Filename: "", - MaxLines: 1000000, - MaxSize: 1 << 28, //256 MB - Daily: true, - MaxDays: 7, - Rotate: true, - Level: LevelTrace, - Perm: 0660, + Filename: "", + MaxLines: 1000000, + MaxSize: 1 << 28, //256 MB + Daily: true, + MaxDays: 7, + Rotate: true, + Level: LevelTrace, + Perm: 0660, + MuxWriter: new(MuxWriter), } - // use MuxWriter instead direct use os.File for lock write when rotate - w.mw = new(MuxWriter) // set MuxWriter as Logger's io.Writer - w.Logger = log.New(w.mw, "", log.Ldate|log.Ltime) + w.Logger = log.New(w, "", log.Ldate|log.Ltime) return w } @@ -126,7 +125,7 @@ func (w *fileLogWriter) startLogger() error { if err != nil { return err } - w.mw.SetFd(fd) + w.SetFd(fd) return w.initFd() } @@ -163,7 +162,7 @@ func (w *fileLogWriter) createLogFile() (*os.File, error) { } func (w *fileLogWriter) initFd() error { - fd := w.mw.fd + fd := w.fd finfo, err := fd.Stat() if err != nil { return fmt.Errorf("get stat err: %s\n", err) @@ -215,15 +214,15 @@ func (w *fileLogWriter) DoRotate() error { if err == nil { // file exists // Find the next available number num := 1 - fname := "" + fName := "" suffix := filepath.Ext(w.Filename) filenameOnly := strings.TrimSuffix(w.Filename, suffix) if suffix == "" { suffix = ".log" } for ; err == nil && num <= 999; num++ { - fname = filenameOnly + fmt.Sprintf(".%s.%03d%s", time.Now().Format("2006-01-02"), num, suffix) - _, err = os.Lstat(fname) + fName = filenameOnly + fmt.Sprintf(".%s.%03d%s", time.Now().Format("2006-01-02"), num, suffix) + _, err = os.Lstat(fName) } // return error if the last file checked still existed if err == nil { @@ -231,15 +230,15 @@ func (w *fileLogWriter) DoRotate() error { } // block Logger's io.Writer - w.mw.Lock() - defer w.mw.Unlock() + w.Lock() + defer w.Unlock() - fd := w.mw.fd + fd := w.fd fd.Close() // close fd before rename // Rename the file to its newfound home - err = os.Rename(w.Filename, fname) + err = os.Rename(w.Filename, fName) if err != nil { return fmt.Errorf("Rotate: %s\n", err) } @@ -277,14 +276,14 @@ func (w *fileLogWriter) deleteOldLog() { // Destroy close the file description, close file writer. func (w *fileLogWriter) Destroy() { - w.mw.fd.Close() + w.fd.Close() } // Flush flush file logger. // there are no buffering messages in file logger in memory. // flush file means sync file from disk. func (w *fileLogWriter) Flush() { - w.mw.fd.Sync() + w.fd.Sync() } func init() { From baa2e9d64a5eae33e5246a07cf5d106d5d1da653 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 19:44:28 +0800 Subject: [PATCH 06/17] code format --- logs/file.go | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/logs/file.go b/logs/file.go index 193a7cc6..16c23de5 100644 --- a/logs/file.go +++ b/logs/file.go @@ -131,17 +131,20 @@ func (w *fileLogWriter) startLogger() error { func (w *fileLogWriter) doCheck(size int) { w.startLock.Lock() - defer w.startLock.Unlock() - if w.Rotate && ((w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) || - (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) - return + if w.Rotate { + if (w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) || + (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.startLock.Unlock() + return + } } } w.maxLinesCurLines++ w.maxSizeCurSize += size + w.startLock.Unlock() } // WriteMsg write logger message into file. @@ -163,14 +166,14 @@ func (w *fileLogWriter) createLogFile() (*os.File, error) { func (w *fileLogWriter) initFd() error { fd := w.fd - finfo, err := fd.Stat() + fInfo, err := fd.Stat() if err != nil { return fmt.Errorf("get stat err: %s\n", err) } - w.maxSizeCurSize = int(finfo.Size()) + w.maxSizeCurSize = int(fInfo.Size()) w.dailyOpenDate = time.Now().Day() w.maxLinesCurLines = 0 - if finfo.Size() > 0 { + if fInfo.Size() > 0 { count, err := w.lines() if err != nil { return err @@ -211,7 +214,8 @@ func (w *fileLogWriter) lines() (int, error) { // new file name like xx.2013-01-01.2.log func (w *fileLogWriter) DoRotate() error { _, err := os.Lstat(w.Filename) - if err == nil { // file exists + if err == nil { + // file exists // Find the next available number num := 1 fName := "" @@ -237,7 +241,7 @@ func (w *fileLogWriter) DoRotate() error { fd.Close() // close fd before rename - // Rename the file to its newfound home + // Rename the file to its new found name err = os.Rename(w.Filename, fName) if err != nil { return fmt.Errorf("Rotate: %s\n", err) @@ -260,8 +264,7 @@ func (w *fileLogWriter) deleteOldLog() { filepath.Walk(dir, func(path string, info os.FileInfo, err error) (returnErr error) { defer func() { if r := recover(); r != nil { - returnErr = fmt.Errorf("Unable to delete old log '%s', error: %+v", path, r) - fmt.Println(returnErr) + fmt.Fprintf(os.Stderr, "Unable to delete old log '%s', error: %+v", path, r) } }() From 482b7a62bda3ec44cacc3949f579ff1e05960341 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 21:05:06 +0800 Subject: [PATCH 07/17] use array not map --- logs/log.go | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/logs/log.go b/logs/log.go index 28b5937c..7e6e1f15 100644 --- a/logs/log.go +++ b/logs/log.go @@ -35,6 +35,7 @@ package logs import ( "fmt" + "os" "path" "runtime" "sync" @@ -95,7 +96,12 @@ type BeeLogger struct { loggerFuncCallDepth int asynchronous bool msg chan *logMsg - outputs map[string]Logger + outputs []*nameLogger +} + +type nameLogger struct { + Logger + name string } type logMsg struct { @@ -104,14 +110,13 @@ type logMsg struct { } // NewLogger returns a new BeeLogger. -// channellen means the number of messages in chan. +// channelLen means the number of messages in chan(used where asynchronous is true). // if the buffering chan is full, logger adapters write to file or other way. -func NewLogger(channellen int64) *BeeLogger { +func NewLogger(channelLen int64) *BeeLogger { bl := new(BeeLogger) bl.level = LevelDebug bl.loggerFuncCallDepth = 2 - bl.msg = make(chan *logMsg, channellen) - bl.outputs = make(map[string]Logger) + bl.msg = make(chan *logMsg, channelLen) return bl } @@ -124,33 +129,40 @@ func (bl *BeeLogger) Async() *BeeLogger { // SetLogger provides a given logger adapter into BeeLogger with config string. // config need to be correct JSON as string: {"interval":360}. -func (bl *BeeLogger) SetLogger(adaptername string, config string) error { +func (bl *BeeLogger) SetLogger(adapterName string, config string) error { bl.lock.Lock() defer bl.lock.Unlock() - if log, ok := adapters[adaptername]; ok { + if log, ok := adapters[adapterName]; ok { lg := log() err := lg.Init(config) - bl.outputs[adaptername] = lg if err != nil { - fmt.Println("logs.BeeLogger.SetLogger: " + err.Error()) + fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error()) return err } + bl.outputs = append(bl.outputs, &nameLogger{name: adapterName, Logger: lg}) } else { - return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adaptername) + return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName) } return nil } // DelLogger remove a logger adapter in BeeLogger. -func (bl *BeeLogger) DelLogger(adaptername string) error { +func (bl *BeeLogger) DelLogger(adapterName string) error { bl.lock.Lock() defer bl.lock.Unlock() - if lg, ok := bl.outputs[adaptername]; ok { - lg.Destroy() - delete(bl.outputs, adaptername) - return nil + outputs := []*nameLogger{} + for _, lg := range bl.outputs { + if lg.name == adapterName { + lg.Destroy() + } else { + outputs = append(outputs, lg) + } } - return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adaptername) + if len(outputs) == len(bl.outputs) { + return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName) + } + bl.outputs = outputs + return nil } func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { @@ -170,10 +182,10 @@ func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { if bl.asynchronous { bl.msg <- lm } else { - for name, l := range bl.outputs { + for _, l := range bl.outputs { err := l.WriteMsg(lm.msg, lm.level) if err != nil { - fmt.Println("unable to WriteMsg to adapter:", name, err) + fmt.Println("unable to WriteMsg to adapter:", l.name, err) return err } } From 12e7f0f94a754879d1343ce8f040481bb170943d Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 21:15:25 +0800 Subject: [PATCH 08/17] extract a func to write to every logger --- logs/log.go | 55 +++++++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/logs/log.go b/logs/log.go index 7e6e1f15..295b0811 100644 --- a/logs/log.go +++ b/logs/log.go @@ -165,7 +165,16 @@ func (bl *BeeLogger) DelLogger(adapterName string) error { return nil } -func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { +func (bl *BeeLogger) writeToLoggers(msg string, level int) { + for _, l := range bl.outputs { + err := l.WriteMsg(msg, level) + if err != nil { + fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err) + } + } +} + +func (bl *BeeLogger) writeMsg(loglevel int, msg string) error { lm := new(logMsg) lm.level = loglevel if bl.enableFuncCallDepth { @@ -182,13 +191,7 @@ func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { if bl.asynchronous { bl.msg <- lm } else { - for _, l := range bl.outputs { - err := l.WriteMsg(lm.msg, lm.level) - if err != nil { - fmt.Println("unable to WriteMsg to adapter:", l.name, err) - return err - } - } + bl.writeToLoggers(msg, loglevel) } return nil } @@ -221,12 +224,7 @@ func (bl *BeeLogger) startLogger() { for { select { case bm := <-bl.msg: - for _, l := range bl.outputs { - err := l.WriteMsg(bm.msg, bm.level) - if err != nil { - fmt.Println("ERROR, unable to WriteMsg:", err) - } - } + bl.writeToLoggers(bm.msg, bm.level) } } } @@ -237,7 +235,7 @@ func (bl *BeeLogger) Emergency(format string, v ...interface{}) { return } msg := fmt.Sprintf("[M] "+format, v...) - bl.writerMsg(LevelEmergency, msg) + bl.writeMsg(LevelEmergency, msg) } // Alert Log ALERT level message. @@ -246,7 +244,7 @@ func (bl *BeeLogger) Alert(format string, v ...interface{}) { return } msg := fmt.Sprintf("[A] "+format, v...) - bl.writerMsg(LevelAlert, msg) + bl.writeMsg(LevelAlert, msg) } // Critical Log CRITICAL level message. @@ -255,7 +253,7 @@ func (bl *BeeLogger) Critical(format string, v ...interface{}) { return } msg := fmt.Sprintf("[C] "+format, v...) - bl.writerMsg(LevelCritical, msg) + bl.writeMsg(LevelCritical, msg) } // Error Log ERROR level message. @@ -264,7 +262,7 @@ func (bl *BeeLogger) Error(format string, v ...interface{}) { return } msg := fmt.Sprintf("[E] "+format, v...) - bl.writerMsg(LevelError, msg) + bl.writeMsg(LevelError, msg) } // Warning Log WARNING level message. @@ -273,7 +271,7 @@ func (bl *BeeLogger) Warning(format string, v ...interface{}) { return } msg := fmt.Sprintf("[W] "+format, v...) - bl.writerMsg(LevelWarning, msg) + bl.writeMsg(LevelWarning, msg) } // Notice Log NOTICE level message. @@ -282,7 +280,7 @@ func (bl *BeeLogger) Notice(format string, v ...interface{}) { return } msg := fmt.Sprintf("[N] "+format, v...) - bl.writerMsg(LevelNotice, msg) + bl.writeMsg(LevelNotice, msg) } // Informational Log INFORMATIONAL level message. @@ -291,7 +289,7 @@ func (bl *BeeLogger) Informational(format string, v ...interface{}) { return } msg := fmt.Sprintf("[I] "+format, v...) - bl.writerMsg(LevelInformational, msg) + bl.writeMsg(LevelInformational, msg) } // Debug Log DEBUG level message. @@ -300,7 +298,7 @@ func (bl *BeeLogger) Debug(format string, v ...interface{}) { return } msg := fmt.Sprintf("[D] "+format, v...) - bl.writerMsg(LevelDebug, msg) + bl.writeMsg(LevelDebug, msg) } // Warn Log WARN level message. @@ -310,7 +308,7 @@ func (bl *BeeLogger) Warn(format string, v ...interface{}) { return } msg := fmt.Sprintf("[W] "+format, v...) - bl.writerMsg(LevelWarning, msg) + bl.writeMsg(LevelWarning, msg) } // Info Log INFO level message. @@ -320,7 +318,7 @@ func (bl *BeeLogger) Info(format string, v ...interface{}) { return } msg := fmt.Sprintf("[I] "+format, v...) - bl.writerMsg(LevelInformational, msg) + bl.writeMsg(LevelInformational, msg) } // Trace Log TRACE level message. @@ -330,7 +328,7 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) { return } msg := fmt.Sprintf("[D] "+format, v...) - bl.writerMsg(LevelDebug, msg) + bl.writeMsg(LevelDebug, msg) } // Flush flush all chan data. @@ -345,12 +343,7 @@ func (bl *BeeLogger) Close() { for { if len(bl.msg) > 0 { bm := <-bl.msg - for _, l := range bl.outputs { - err := l.WriteMsg(bm.msg, bm.level) - if err != nil { - fmt.Println("ERROR, unable to WriteMsg (while closing logger):", err) - } - } + bl.writeToLoggers(bm.msg, bm.level) continue } break From bd0f3c29fabfca168f998df2e5f9c82241b7337b Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 22:32:20 +0800 Subject: [PATCH 09/17] decr malloc new object --- logs/log.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/logs/log.go b/logs/log.go index 295b0811..f68202f4 100644 --- a/logs/log.go +++ b/logs/log.go @@ -174,9 +174,7 @@ func (bl *BeeLogger) writeToLoggers(msg string, level int) { } } -func (bl *BeeLogger) writeMsg(loglevel int, msg string) error { - lm := new(logMsg) - lm.level = loglevel +func (bl *BeeLogger) writeMsg(logLevel int, msg string) error { if bl.enableFuncCallDepth { _, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth) if !ok { @@ -184,14 +182,17 @@ func (bl *BeeLogger) writeMsg(loglevel int, msg string) error { line = 0 } _, filename := path.Split(file) - lm.msg = fmt.Sprintf("[%s:%d] %s", filename, line, msg) + msg = fmt.Sprintf("[%s:%d] %s", filename, line, msg) } else { - lm.msg = msg + msg = msg } if bl.asynchronous { + lm := new(logMsg) + lm.level = logLevel + lm.msg = msg bl.msg <- lm } else { - bl.writeToLoggers(msg, loglevel) + bl.writeToLoggers(msg, logLevel) } return nil } From 2b9d7ff714f0b7d6cd12534ed0cd7fba5ebaceac Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 22:32:36 +0800 Subject: [PATCH 10/17] remove log package --- logs/file.go | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/logs/file.go b/logs/file.go index 16c23de5..9ee7f694 100644 --- a/logs/file.go +++ b/logs/file.go @@ -20,7 +20,6 @@ import ( "errors" "fmt" "io" - "log" "os" "path/filepath" "strings" @@ -31,7 +30,6 @@ import ( // fileLogWriter implements LoggerInterface. // It writes messages by lines limit, file size limit, or time frequency. type fileLogWriter struct { - *log.Logger *MuxWriter // The opened file Filename string `json:"filename"` @@ -91,8 +89,6 @@ func newFileWriter() Logger { Perm: 0660, MuxWriter: new(MuxWriter), } - // set MuxWriter as Logger's io.Writer - w.Logger = log.New(w, "", log.Ldate|log.Ltime) return w } @@ -137,8 +133,6 @@ func (w *fileLogWriter) doCheck(size int) { (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.startLock.Unlock() - return } } } @@ -152,9 +146,47 @@ func (w *fileLogWriter) WriteMsg(msg string, level int) error { if level > w.Level { return nil } - n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] " - w.doCheck(n) - w.Logger.Println(msg) + //2016/01/12 21:34:33 + now := time.Now() + y, mo, d := now.Date() + h, mi, s := now.Clock() + //len(2006/01/02 15:03:04)==19 + var buf [19]byte + t := 3 + for y >= 10 { + p := y / 10 + buf[t] = byte('0' + y - p*10) + y = p + t-- + } + buf[0] = byte('0' + y) + buf[4] = '/' + if mo > 9 { + buf[5] = '1' + buf[6] = byte('0' + mo - 9) + } else { + buf[5] = '0' + buf[6] = byte('0' + mo) + } + buf[7] = '/' + t = d / 10 + buf[8] = byte('0' + t) + buf[9] = byte('0' + d - t*10) + buf[10] = ' ' + t = h / 10 + buf[11] = byte('0' + t) + buf[12] = byte('0' + h - t*10) + buf[13] = ':' + t = mi / 10 + buf[14] = byte('0' + t) + buf[15] = byte('0' + mi - t*10) + buf[16] = ':' + t = s / 10 + buf[17] = byte('0' + t) + buf[18] = byte('0' + s - t*10) + msg = string(buf[0:]) + msg + "\n" + w.doCheck(len(msg)) + w.fd.Write([]byte(msg)) return nil } @@ -264,7 +296,7 @@ func (w *fileLogWriter) deleteOldLog() { filepath.Walk(dir, func(path string, info os.FileInfo, err error) (returnErr error) { defer func() { if r := recover(); r != nil { - fmt.Fprintf(os.Stderr, "Unable to delete old log '%s', error: %+v", path, r) + fmt.Fprintf(os.Stderr, "Unable to delete old log '%s', error: %v\n", path, r) } }() From 164366ae0da801fd310de432fdcabe0fd4ac9aab Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 22:33:52 +0800 Subject: [PATCH 11/17] return error --- logs/file.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/logs/file.go b/logs/file.go index 9ee7f694..b9336a2c 100644 --- a/logs/file.go +++ b/logs/file.go @@ -185,9 +185,10 @@ func (w *fileLogWriter) WriteMsg(msg string, level int) error { buf[17] = byte('0' + t) buf[18] = byte('0' + s - t*10) msg = string(buf[0:]) + msg + "\n" + w.doCheck(len(msg)) - w.fd.Write([]byte(msg)) - return nil + _, err := w.fd.Write([]byte(msg)) + return err } func (w *fileLogWriter) createLogFile() (*os.File, error) { From 69804afc1b00558337c4d1f4119ca4046ac6073d Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 22:39:40 +0800 Subject: [PATCH 12/17] use pool to logMsg --- logs/log.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/logs/log.go b/logs/log.go index f68202f4..0a099dfe 100644 --- a/logs/log.go +++ b/logs/log.go @@ -95,7 +95,7 @@ type BeeLogger struct { enableFuncCallDepth bool loggerFuncCallDepth int asynchronous bool - msg chan *logMsg + msgChan chan *logMsg outputs []*nameLogger } @@ -109,6 +109,8 @@ type logMsg struct { msg string } +var logMsgPool *sync.Pool + // NewLogger returns a new BeeLogger. // channelLen means the number of messages in chan(used where asynchronous is true). // if the buffering chan is full, logger adapters write to file or other way. @@ -116,13 +118,18 @@ func NewLogger(channelLen int64) *BeeLogger { bl := new(BeeLogger) bl.level = LevelDebug bl.loggerFuncCallDepth = 2 - bl.msg = make(chan *logMsg, channelLen) + bl.msgChan = make(chan *logMsg, channelLen) return bl } // Async set the log to asynchronous and start the goroutine func (bl *BeeLogger) Async() *BeeLogger { bl.asynchronous = true + logMsgPool = &sync.Pool{ + New: func() interface{} { + return &logMsg{} + }, + } go bl.startLogger() return bl } @@ -187,10 +194,10 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string) error { msg = msg } if bl.asynchronous { - lm := new(logMsg) + lm := logMsgPool.Get().(*logMsg) lm.level = logLevel lm.msg = msg - bl.msg <- lm + bl.msgChan <- lm } else { bl.writeToLoggers(msg, logLevel) } @@ -224,8 +231,9 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) { func (bl *BeeLogger) startLogger() { for { select { - case bm := <-bl.msg: + case bm := <-bl.msgChan: bl.writeToLoggers(bm.msg, bm.level) + logMsgPool.Put(bm) } } } @@ -342,9 +350,10 @@ func (bl *BeeLogger) Flush() { // Close close logger, flush all chan data and destroy all adapters in BeeLogger. func (bl *BeeLogger) Close() { for { - if len(bl.msg) > 0 { - bm := <-bl.msg + if len(bl.msgChan) > 0 { + bm := <-bl.msgChan bl.writeToLoggers(bm.msg, bm.level) + logMsgPool.Put(bm) continue } break From c535dc386e323ef3f92db52728dcca8b60c2a065 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Jan 2016 22:54:39 +0800 Subject: [PATCH 13/17] fast format --- logs/log.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/logs/log.go b/logs/log.go index 0a099dfe..12f7f2e7 100644 --- a/logs/log.go +++ b/logs/log.go @@ -38,6 +38,7 @@ import ( "os" "path" "runtime" + "strconv" "sync" ) @@ -189,7 +190,7 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string) error { line = 0 } _, filename := path.Split(file) - msg = fmt.Sprintf("[%s:%d] %s", filename, line, msg) + msg = "[" + filename + ":" + strconv.FormatInt(int64(line), 10) + "]" + msg } else { msg = msg } From e1b73b33d09674e0c1fa2d5807a0e498ca4923b3 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 13 Jan 2016 08:21:44 +0800 Subject: [PATCH 14/17] improve code --- logs/file.go | 40 +++++++++++++++++++++------------------- logs/log.go | 2 -- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/logs/file.go b/logs/file.go index b9336a2c..a5f1dd2f 100644 --- a/logs/file.go +++ b/logs/file.go @@ -48,7 +48,7 @@ type fileLogWriter struct { Rotate bool `json:"rotate"` - startLock sync.Mutex // Only one log can write to the file + startLock sync.Mutex // atomic incr maxLinesCurLines and maxSizeCurSize Level int `json:"level"` @@ -58,22 +58,23 @@ type fileLogWriter struct { // MuxWriter is an *os.File writer with locker,lock write when rotate type MuxWriter struct { sync.Mutex - fd *os.File + fileWriter *os.File } // Write to os.File. -func (l *MuxWriter) Write(b []byte) (int, error) { - l.Lock() - defer l.Unlock() - return l.fd.Write(b) +func (mw *MuxWriter) Write(b []byte) (int, error) { + mw.Lock() + n, e := mw.fileWriter.Write(b) + mw.Unlock() + return n, e } -// SetFd set os.File in writer. -func (l *MuxWriter) SetFd(fd *os.File) { - if l.fd != nil { - l.fd.Close() +// SetFileWriter set os.File in writer. +func (mw *MuxWriter) SetFileWriter(fd *os.File) { + if mw.fileWriter != nil { + mw.fileWriter.Close() } - l.fd = fd + mw.fileWriter = fd } // NewFileWriter create a FileLogWriter returning as LoggerInterface. @@ -117,11 +118,11 @@ func (w *fileLogWriter) Init(jsonConfig string) error { // start file logger. create log file and set to locker-inside file writer. func (w *fileLogWriter) startLogger() error { - fd, err := w.createLogFile() + file, err := w.createLogFile() if err != nil { return err } - w.SetFd(fd) + w.SetFileWriter(file) return w.initFd() } @@ -151,7 +152,7 @@ func (w *fileLogWriter) WriteMsg(msg string, level int) error { y, mo, d := now.Date() h, mi, s := now.Clock() //len(2006/01/02 15:03:04)==19 - var buf [19]byte + var buf [20]byte t := 3 for y >= 10 { p := y / 10 @@ -184,10 +185,11 @@ func (w *fileLogWriter) WriteMsg(msg string, level int) error { t = s / 10 buf[17] = byte('0' + t) buf[18] = byte('0' + s - t*10) + buf[18] = ' ' msg = string(buf[0:]) + msg + "\n" w.doCheck(len(msg)) - _, err := w.fd.Write([]byte(msg)) + _, err := w.Write([]byte(msg)) return err } @@ -198,7 +200,7 @@ func (w *fileLogWriter) createLogFile() (*os.File, error) { } func (w *fileLogWriter) initFd() error { - fd := w.fd + fd := w.fileWriter fInfo, err := fd.Stat() if err != nil { return fmt.Errorf("get stat err: %s\n", err) @@ -270,7 +272,7 @@ func (w *fileLogWriter) DoRotate() error { w.Lock() defer w.Unlock() - fd := w.fd + fd := w.fileWriter fd.Close() // close fd before rename @@ -312,14 +314,14 @@ func (w *fileLogWriter) deleteOldLog() { // Destroy close the file description, close file writer. func (w *fileLogWriter) Destroy() { - w.fd.Close() + w.fileWriter.Close() } // Flush flush file logger. // there are no buffering messages in file logger in memory. // flush file means sync file from disk. func (w *fileLogWriter) Flush() { - w.fd.Sync() + w.fileWriter.Sync() } func init() { diff --git a/logs/log.go b/logs/log.go index 12f7f2e7..ccaaa3ad 100644 --- a/logs/log.go +++ b/logs/log.go @@ -191,8 +191,6 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string) error { } _, filename := path.Split(file) msg = "[" + filename + ":" + strconv.FormatInt(int64(line), 10) + "]" + msg - } else { - msg = msg } if bl.asynchronous { lm := logMsgPool.Get().(*logMsg) From 58730e3528ccdb30fc69ccb34ff54a11ff06c10b Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 13 Jan 2016 09:21:32 +0800 Subject: [PATCH 15/17] test file modify --- logs/file_test.go | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/logs/file_test.go b/logs/file_test.go index d03d3ca5..f9b54c26 100644 --- a/logs/file_test.go +++ b/logs/file_test.go @@ -23,7 +23,7 @@ import ( "time" ) -func TestFile(t *testing.T) { +func TestFile1(t *testing.T) { log := NewLogger(10000) log.SetLogger("file", `{"filename":"test.log"}`) log.Debug("debug") @@ -34,25 +34,24 @@ func TestFile(t *testing.T) { log.Alert("alert") log.Critical("critical") log.Emergency("emergency") - time.Sleep(time.Second * 4) f, err := os.Open("test.log") if err != nil { t.Fatal(err) } b := bufio.NewReader(f) - linenum := 0 + lineNum := 0 for { line, _, err := b.ReadLine() if err != nil { break } if len(line) > 0 { - linenum++ + lineNum++ } } var expected = LevelDebug + 1 - if linenum != expected { - t.Fatal(linenum, "not "+strconv.Itoa(expected)+" lines") + if lineNum != expected { + t.Fatal(lineNum, "not "+strconv.Itoa(expected)+" lines") } os.Remove("test.log") } @@ -68,25 +67,24 @@ func TestFile2(t *testing.T) { log.Alert("alert") log.Critical("critical") log.Emergency("emergency") - time.Sleep(time.Second * 4) f, err := os.Open("test2.log") if err != nil { t.Fatal(err) } b := bufio.NewReader(f) - linenum := 0 + lineNum := 0 for { line, _, err := b.ReadLine() if err != nil { break } if len(line) > 0 { - linenum++ + lineNum++ } } var expected = LevelError + 1 - if linenum != expected { - t.Fatal(linenum, "not "+strconv.Itoa(expected)+" lines") + if lineNum != expected { + t.Fatal(lineNum, "not "+strconv.Itoa(expected)+" lines") } os.Remove("test2.log") } @@ -102,13 +100,13 @@ func TestFileRotate(t *testing.T) { log.Alert("alert") log.Critical("critical") log.Emergency("emergency") - time.Sleep(time.Second * 4) - rotatename := "test3" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1) + ".log" - b, err := exists(rotatename) + rotateName := "test3" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1) + ".log" + b, err := exists(rotateName) if !b || err != nil { + os.Remove("test3.log") t.Fatal("rotate not generated") } - os.Remove(rotatename) + os.Remove(rotateName) os.Remove("test3.log") } @@ -132,7 +130,8 @@ func BenchmarkFile(b *testing.B) { os.Remove("test4.log") } -func BenchmarkAsynchronousFile(b *testing.B) { + +func BenchmarkFileAsynchronous(b *testing.B) { log := NewLogger(100000) log.SetLogger("file", `{"filename":"test4.log"}`) log.Async() @@ -142,7 +141,7 @@ func BenchmarkAsynchronousFile(b *testing.B) { os.Remove("test4.log") } -func BenchmarkCallDepthFile(b *testing.B) { +func BenchmarkFileCallDepth(b *testing.B) { log := NewLogger(100000) log.SetLogger("file", `{"filename":"test4.log"}`) log.EnableFuncCallDepth(true) @@ -153,7 +152,7 @@ func BenchmarkCallDepthFile(b *testing.B) { os.Remove("test4.log") } -func BenchmarkAsynchronousCallDepthFile(b *testing.B) { +func BenchmarkFileAsynchronousCallDepth(b *testing.B) { log := NewLogger(100000) log.SetLogger("file", `{"filename":"test4.log"}`) log.EnableFuncCallDepth(true) @@ -164,3 +163,12 @@ func BenchmarkAsynchronousCallDepthFile(b *testing.B) { } os.Remove("test4.log") } + +func BenchmarkFileOnGoroutine(b *testing.B) { + log := NewLogger(100000) + log.SetLogger("file", `{"filename":"test4.log"}`) + for i := 0; i < b.N; i++ { + go log.Debug("debug") + } + os.Remove("test4.log") +} From 7663d50c9719ec941399874c7179e075b0b8e5e1 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 13 Jan 2016 09:21:55 +0800 Subject: [PATCH 16/17] remove the lock writer --- logs/file.go | 126 ++++++++++++++++++++++----------------------------- 1 file changed, 55 insertions(+), 71 deletions(-) diff --git a/logs/file.go b/logs/file.go index a5f1dd2f..6d5f89ba 100644 --- a/logs/file.go +++ b/logs/file.go @@ -30,10 +30,12 @@ import ( // fileLogWriter implements LoggerInterface. // It writes messages by lines limit, file size limit, or time frequency. type fileLogWriter struct { - *MuxWriter + sync.Mutex // write log order by order and atomic incr maxLinesCurLines and maxSizeCurSize // The opened file - Filename string `json:"filename"` + Filename string `json:"filename"` + fileWriter *os.File + // Rotate at line MaxLines int `json:"maxlines"` maxLinesCurLines int @@ -48,47 +50,22 @@ type fileLogWriter struct { Rotate bool `json:"rotate"` - startLock sync.Mutex // atomic incr maxLinesCurLines and maxSizeCurSize - Level int `json:"level"` 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. func newFileWriter() Logger { w := &fileLogWriter{ - Filename: "", - MaxLines: 1000000, - MaxSize: 1 << 28, //256 MB - Daily: true, - MaxDays: 7, - Rotate: true, - Level: LevelTrace, - Perm: 0660, - MuxWriter: new(MuxWriter), + Filename: "", + MaxLines: 1000000, + MaxSize: 1 << 28, //256 MB + Daily: true, + MaxDays: 7, + Rotate: true, + Level: LevelTrace, + Perm: 0660, } return w } @@ -122,24 +99,18 @@ func (w *fileLogWriter) startLogger() error { if err != nil { return err } - w.SetFileWriter(file) + if w.fileWriter != nil { + w.fileWriter.Close() + } + w.fileWriter = file return w.initFd() } -func (w *fileLogWriter) doCheck(size int) { - w.startLock.Lock() - if w.Rotate { - if (w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) || - (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() +func (w *fileLogWriter) needRotate(size int, day int) bool { + return (w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) || + (w.MaxSize > 0 && w.maxSizeCurSize >= w.MaxSize) || + (w.Daily && day != w.dailyOpenDate) + } // WriteMsg write logger message into file. @@ -185,11 +156,29 @@ func (w *fileLogWriter) WriteMsg(msg string, level int) error { t = s / 10 buf[17] = byte('0' + t) buf[18] = byte('0' + s - t*10) - buf[18] = ' ' + buf[19] = ' ' msg = string(buf[0:]) + msg + "\n" - w.doCheck(len(msg)) - _, err := w.Write([]byte(msg)) + if w.Rotate { + 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 } @@ -247,7 +236,7 @@ func (w *fileLogWriter) lines() (int, error) { // DoRotate means it need to write file in new file. // 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) if err == nil { // 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) } - // block Logger's io.Writer - w.Lock() - defer w.Unlock() + // close fileWriter before rename + w.fileWriter.Close() - fd := w.fileWriter - fd.Close() - - // close fd before rename // Rename the file to its new found name - err = os.Rename(w.Filename, fName) - if err != nil { - return fmt.Errorf("Rotate: %s\n", err) - } - + // even if occurs error,we MUST guarantee to restart new logger + renameErr := os.Rename(w.Filename, fName) // re-start logger - err = w.startLogger() - if err != nil { - return fmt.Errorf("Rotate StartLogger: %s\n", err) - } - + startLoggerErr := w.startLogger() 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 From fb5b04506abe3826bde67399add19259808e3f5f Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 13 Jan 2016 09:24:27 +0800 Subject: [PATCH 17/17] code refactor and format --- logs/file.go | 69 ++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/logs/file.go b/logs/file.go index 6d5f89ba..0eae734a 100644 --- a/logs/file.go +++ b/logs/file.go @@ -238,44 +238,45 @@ func (w *fileLogWriter) lines() (int, error) { // new file name like xx.2013-01-01.2.log func (w *fileLogWriter) doRotate() error { _, err := os.Lstat(w.Filename) + if err != nil { + return err + } + // file exists + // Find the next available number + num := 1 + fName := "" + suffix := filepath.Ext(w.Filename) + filenameOnly := strings.TrimSuffix(w.Filename, suffix) + if suffix == "" { + suffix = ".log" + } + for ; err == nil && num <= 999; num++ { + fName = filenameOnly + fmt.Sprintf(".%s.%03d%s", time.Now().Format("2006-01-02"), num, suffix) + _, err = os.Lstat(fName) + } + // return error if the last file checked still existed if err == nil { - // file exists - // Find the next available number - num := 1 - fName := "" - suffix := filepath.Ext(w.Filename) - filenameOnly := strings.TrimSuffix(w.Filename, suffix) - if suffix == "" { - suffix = ".log" - } - for ; err == nil && num <= 999; num++ { - fName = filenameOnly + fmt.Sprintf(".%s.%03d%s", time.Now().Format("2006-01-02"), num, suffix) - _, err = os.Lstat(fName) - } - // return error if the last file checked still existed - if err == nil { - return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.Filename) - } - - // close fileWriter before rename - w.fileWriter.Close() - - // Rename the file to its new found name - // even if occurs error,we MUST guarantee to restart new logger - renameErr := os.Rename(w.Filename, fName) - // re-start logger - startLoggerErr := w.startLogger() - 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 fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.Filename) } + // close fileWriter before rename + w.fileWriter.Close() + + // Rename the file to its new found name + // even if occurs error,we MUST guarantee to restart new logger + renameErr := os.Rename(w.Filename, fName) + // re-start logger + startLoggerErr := w.startLogger() + 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 + } func (w *fileLogWriter) deleteOldLog() {