From ecab397073bf1585048849fa74f03084169235f2 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Thu, 28 Jan 2016 21:53:44 +0800 Subject: [PATCH 1/2] try to fix the little bug when calling Close or Flush in async mode --- logs/log.go | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/logs/log.go b/logs/log.go index 2a12ed79..0323e0d3 100644 --- a/logs/log.go +++ b/logs/log.go @@ -98,6 +98,8 @@ type BeeLogger struct { loggerFuncCallDepth int asynchronous bool msgChan chan *logMsg + signalChan chan string + wg sync.WaitGroup outputs []*nameLogger } @@ -122,6 +124,8 @@ func NewLogger(channelLen int64) *BeeLogger { bl.level = LevelDebug bl.loggerFuncCallDepth = 2 bl.msgChan = make(chan *logMsg, channelLen) + bl.signalChan = make(chan string, 1) + bl.wg.Add(1) return bl } @@ -237,6 +241,27 @@ func (bl *BeeLogger) startLogger() { case bm := <-bl.msgChan: bl.writeToLoggers(bm.when, bm.msg, bm.level) logMsgPool.Put(bm) + case sg := <-bl.signalChan: + // Now should only send "flush" or "close" to bl.signalChan + for { + if len(bl.msgChan) > 0 { + bm := <-bl.msgChan + bl.writeToLoggers(bm.when, bm.msg, bm.level) + logMsgPool.Put(bm) + continue + } + break + } + for _, l := range bl.outputs { + l.Flush() + } + if sg == "close" { + for _, l := range bl.outputs { + l.Destroy() + } + bl.outputs = nil + } + bl.wg.Done() } } } @@ -345,27 +370,16 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) { // Flush flush all chan data. func (bl *BeeLogger) Flush() { - for _, l := range bl.outputs { - l.Flush() - } + bl.signalChan <- "flush" + bl.wg.Wait() + bl.wg.Add(1) } // Close close logger, flush all chan data and destroy all adapters in BeeLogger. func (bl *BeeLogger) Close() { - for { - if len(bl.msgChan) > 0 { - bm := <-bl.msgChan - bl.writeToLoggers(bm.when, bm.msg, bm.level) - logMsgPool.Put(bm) - continue - } - break - } - for _, l := range bl.outputs { - l.Flush() - l.Destroy() - } - bl.outputs = nil + bl.signalChan <- "close" + bl.wg.Wait() + bl.wg.Add(1) } func formatLogTime(when time.Time) string { From 2efe7c4c89dc9ca5120f2762db46ce731f265945 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Tue, 2 Feb 2016 17:12:47 +0800 Subject: [PATCH 2/2] merge multi commit --- config.go | 4 +-- logs/log.go | 75 +++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/config.go b/config.go index ffe92f06..f9810778 100644 --- a/config.go +++ b/config.go @@ -15,11 +15,11 @@ package beego import ( + "fmt" "html/template" "os" "path/filepath" "strings" - "fmt" "github.com/astaxie/beego/config" "github.com/astaxie/beego/session" @@ -299,7 +299,7 @@ func parseConfig(appConfigPath string) (err error) { } //init log - BeeLogger.Close() + BeeLogger.Reset() for adaptor, config := range BConfig.Log.Outputs { err = BeeLogger.SetLogger(adaptor, config) if err != nil { diff --git a/logs/log.go b/logs/log.go index 0323e0d3..428e8e50 100644 --- a/logs/log.go +++ b/logs/log.go @@ -98,8 +98,8 @@ type BeeLogger struct { loggerFuncCallDepth int asynchronous bool msgChan chan *logMsg - signalChan chan string - wg sync.WaitGroup + signalChan chan string + wg sync.WaitGroup outputs []*nameLogger } @@ -111,7 +111,7 @@ type nameLogger struct { type logMsg struct { level int msg string - when time.Time + when time.Time } var logMsgPool *sync.Pool @@ -125,7 +125,6 @@ func NewLogger(channelLen int64) *BeeLogger { bl.loggerFuncCallDepth = 2 bl.msgChan = make(chan *logMsg, channelLen) bl.signalChan = make(chan string, 1) - bl.wg.Add(1) return bl } @@ -137,6 +136,7 @@ func (bl *BeeLogger) Async() *BeeLogger { return &logMsg{} }, } + bl.wg.Add(1) go bl.startLogger() return bl } @@ -236,6 +236,7 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) { // start logger chan reading. // when chan is not empty, write logs. func (bl *BeeLogger) startLogger() { + gameOver := false for { select { case bm := <-bl.msgChan: @@ -243,26 +244,19 @@ func (bl *BeeLogger) startLogger() { logMsgPool.Put(bm) case sg := <-bl.signalChan: // Now should only send "flush" or "close" to bl.signalChan - for { - if len(bl.msgChan) > 0 { - bm := <-bl.msgChan - bl.writeToLoggers(bm.when, bm.msg, bm.level) - logMsgPool.Put(bm) - continue - } - break - } - for _, l := range bl.outputs { - l.Flush() - } + bl.flush() if sg == "close" { for _, l := range bl.outputs { l.Destroy() } bl.outputs = nil + gameOver = true } bl.wg.Done() } + if gameOver { + break + } } } @@ -370,16 +364,53 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) { // Flush flush all chan data. func (bl *BeeLogger) Flush() { - bl.signalChan <- "flush" - bl.wg.Wait() - bl.wg.Add(1) + if bl.asynchronous { + bl.signalChan <- "flush" + bl.wg.Wait() + bl.wg.Add(1) + return + } + bl.flush() } // Close close logger, flush all chan data and destroy all adapters in BeeLogger. func (bl *BeeLogger) Close() { - bl.signalChan <- "close" - bl.wg.Wait() - bl.wg.Add(1) + if bl.asynchronous { + bl.signalChan <- "close" + bl.wg.Wait() + } else { + bl.flush() + for _, l := range bl.outputs { + l.Destroy() + } + bl.outputs = nil + } + close(bl.msgChan) + close(bl.signalChan) +} + +// Reset close all outputs, and set bl.outputs to nil +func (bl *BeeLogger) Reset() { + bl.Flush() + for _, l := range bl.outputs { + l.Destroy() + } + bl.outputs = nil +} + +func (bl *BeeLogger) flush() { + for { + if len(bl.msgChan) > 0 { + bm := <-bl.msgChan + bl.writeToLoggers(bm.when, bm.msg, bm.level) + logMsgPool.Put(bm) + continue + } + break + } + for _, l := range bl.outputs { + l.Flush() + } } func formatLogTime(when time.Time) string {