diff --git a/pkg/logs/accesslog.go b/pkg/logs/accesslog.go index e380c54a..1be711d8 100644 --- a/pkg/logs/accesslog.go +++ b/pkg/logs/accesslog.go @@ -79,5 +79,10 @@ func AccessLog(r *AccessLogRecord, format string) { msg = string(jsonData) } } - beeLogger.writeMsg(levelLoggerImpl, strings.TrimSpace(msg)) + lm := &LogMsg{ + Msg: strings.TrimSpace(msg), + When: time.Now(), + Level: levelLoggerImpl, + } + beeLogger.writeMsg(lm) } diff --git a/pkg/logs/alils/alils.go b/pkg/logs/alils/alils.go index fd1a4e28..1bd6b653 100644 --- a/pkg/logs/alils/alils.go +++ b/pkg/logs/alils/alils.go @@ -4,7 +4,6 @@ import ( "encoding/json" "strings" "sync" - "time" "github.com/astaxie/beego/pkg/logs" "github.com/gogo/protobuf/proto" @@ -103,9 +102,8 @@ func (c *aliLSWriter) Init(jsonConfig string) (err error) { // WriteMsg writes a message in connection. // If connection is down, try to re-connect. -func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error) { - - if level > c.Level { +func (c *aliLSWriter) WriteMsg(lm *logs.LogMsg) error { + if lm.Level > c.Level { return nil } diff --git a/pkg/logs/conn.go b/pkg/logs/conn.go index 8b55bde7..e0560fd9 100644 --- a/pkg/logs/conn.go +++ b/pkg/logs/conn.go @@ -18,7 +18,6 @@ import ( "encoding/json" "io" "net" - "time" ) // connWriter implements LoggerInterface. @@ -48,8 +47,8 @@ func (c *connWriter) Init(jsonConfig string) error { // WriteMsg writes message in connection. // If connection is down, try to re-connect. -func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error { - if level > c.Level { +func (c *connWriter) WriteMsg(lm *LogMsg) error { + if lm.Level > c.Level { return nil } if c.needToConnectOnMsg() { @@ -63,7 +62,7 @@ func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error { defer c.innerWriter.Close() } - _, err := c.lg.writeln(when, msg) + _, err := c.lg.writeln(lm) if err != nil { return err } diff --git a/pkg/logs/console.go b/pkg/logs/console.go index b2cc2907..024152aa 100644 --- a/pkg/logs/console.go +++ b/pkg/logs/console.go @@ -18,7 +18,6 @@ import ( "encoding/json" "os" "strings" - "time" "github.com/shiena/ansicolor" ) @@ -73,14 +72,14 @@ func (c *consoleWriter) Init(jsonConfig string) error { } // WriteMsg writes message in console. -func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { - if level > c.Level { +func (c *consoleWriter) WriteMsg(lm *LogMsg) error { + if lm.Level > c.Level { return nil } if c.Colorful { - msg = strings.Replace(msg, levelPrefix[level], colors[level](levelPrefix[level]), 1) + lm.Msg = strings.Replace(lm.Msg, levelPrefix[lm.Level], colors[lm.Level](levelPrefix[lm.Level]), 1) } - c.lg.writeln(when, msg) + c.lg.writeln(lm) return nil } diff --git a/pkg/logs/file.go b/pkg/logs/file.go index fbe10b55..23ea4b09 100644 --- a/pkg/logs/file.go +++ b/pkg/logs/file.go @@ -144,28 +144,28 @@ func (w *fileLogWriter) needRotateHourly(size int, hour int) bool { } // WriteMsg writes logger message into file. -func (w *fileLogWriter) WriteMsg(when time.Time, msg string, level int) error { - if level > w.Level { +func (w *fileLogWriter) WriteMsg(lm *LogMsg) error { + if lm.Level > w.Level { return nil } - hd, d, h := formatTimeHeader(when) - msg = string(hd) + msg + "\n" + hd, d, h := formatTimeHeader(lm.When) + lm.Msg = string(hd) + lm.Msg + "\n" if w.Rotate { w.RLock() - if w.needRotateHourly(len(msg), h) { + if w.needRotateHourly(len(lm.Msg), h) { w.RUnlock() w.Lock() - if w.needRotateHourly(len(msg), h) { - if err := w.doRotate(when); err != nil { + if w.needRotateHourly(len(lm.Msg), h) { + if err := w.doRotate(lm.When); err != nil { fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err) } } w.Unlock() - } else if w.needRotateDaily(len(msg), d) { + } else if w.needRotateDaily(len(lm.Msg), d) { w.RUnlock() w.Lock() - if w.needRotateDaily(len(msg), d) { - if err := w.doRotate(when); err != nil { + if w.needRotateDaily(len(lm.Msg), d) { + if err := w.doRotate(lm.When); err != nil { fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err) } } @@ -176,10 +176,10 @@ func (w *fileLogWriter) WriteMsg(when time.Time, msg string, level int) error { } w.Lock() - _, err := w.fileWriter.Write([]byte(msg)) + _, err := w.fileWriter.Write([]byte(lm.Msg)) if err == nil { w.maxLinesCurLines++ - w.maxSizeCurSize += len(msg) + w.maxSizeCurSize += len(lm.Msg) } w.Unlock() return err diff --git a/pkg/logs/jianliao.go b/pkg/logs/jianliao.go index 71e7e2bf..0e7cfab4 100644 --- a/pkg/logs/jianliao.go +++ b/pkg/logs/jianliao.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "net/url" - "time" ) // JLWriter implements beego LoggerInterface and is used to send jiaoliao webhook @@ -30,12 +29,12 @@ func (s *JLWriter) Init(jsonconfig string) error { // WriteMsg writes message in smtp writer. // Sends an email with subject and only this message. -func (s *JLWriter) WriteMsg(when time.Time, msg string, level int) error { - if level > s.Level { +func (s *JLWriter) WriteMsg(lm *LogMsg) error { + if lm.Level > s.Level { return nil } - text := fmt.Sprintf("%s %s", when.Format("2006-01-02 15:04:05"), msg) + text := fmt.Sprintf("%s %s", lm.When.Format("2006-01-02 15:04:05"), lm.Msg) form := url.Values{} form.Add("authorName", s.AuthorName) diff --git a/pkg/logs/log.go b/pkg/logs/log.go index 4824918b..3a117327 100644 --- a/pkg/logs/log.go +++ b/pkg/logs/log.go @@ -86,7 +86,7 @@ type newLoggerFunc func() Logger // Logger defines the behavior of a log provider. type Logger interface { Init(config string) error - WriteMsg(when time.Time, msg string, level int) error + WriteMsg(lm *LogMsg) error Destroy() Flush() } @@ -118,7 +118,7 @@ type BeeLogger struct { asynchronous bool prefix string msgChanLen int64 - msgChan chan *logMsg + msgChan chan *LogMsg signalChan chan string wg sync.WaitGroup outputs []*nameLogger @@ -131,10 +131,12 @@ type nameLogger struct { name string } -type logMsg struct { - level int - msg string - when time.Time +type LogMsg struct { + Level int + Msg string + When time.Time + FilePath string + LineNumber int } var logMsgPool *sync.Pool @@ -166,10 +168,10 @@ func (bl *BeeLogger) Async(msgLen ...int64) *BeeLogger { if len(msgLen) > 0 && msgLen[0] > 0 { bl.msgChanLen = msgLen[0] } - bl.msgChan = make(chan *logMsg, bl.msgChanLen) + bl.msgChan = make(chan *LogMsg, bl.msgChanLen) logMsgPool = &sync.Pool{ New: func() interface{} { - return &logMsg{} + return &LogMsg{} }, } bl.wg.Add(1) @@ -233,9 +235,9 @@ func (bl *BeeLogger) DelLogger(adapterName string) error { return nil } -func (bl *BeeLogger) writeToLoggers(when time.Time, msg string, level int) { +func (bl *BeeLogger) writeToLoggers(lm *LogMsg) { for _, l := range bl.outputs { - err := l.WriteMsg(when, msg, level) + err := l.WriteMsg(lm) if err != nil { fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err) } @@ -250,15 +252,20 @@ func (bl *BeeLogger) Write(p []byte) (n int, err error) { if p[len(p)-1] == '\n' { p = p[0 : len(p)-1] } + lm := &LogMsg{ + Msg: string(p), + Level: levelLoggerImpl, + } + // set levelLoggerImpl to ensure all log message will be write out - err = bl.writeMsg(levelLoggerImpl, string(p)) + err = bl.writeMsg(lm) if err == nil { return len(p), err } return 0, err } -func (bl *BeeLogger) writeMsg(logLevel int, msg string, v ...interface{}) error { +func (bl *BeeLogger) writeMsg(lm *LogMsg, v ...interface{}) error { if !bl.init { bl.lock.Lock() bl.setLogger(AdapterConsole) @@ -266,12 +273,11 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string, v ...interface{}) error } if len(v) > 0 { - msg = fmt.Sprintf(msg, v...) + lm.Msg = fmt.Sprintf(lm.Msg, v...) } - msg = bl.prefix + " " + msg + lm.Msg = bl.prefix + " " + lm.Msg - when := time.Now() if bl.enableFuncCallDepth { _, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth) if !ok { @@ -279,29 +285,29 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string, v ...interface{}) error line = 0 } _, filename := path.Split(file) - msg = "[" + filename + ":" + strconv.Itoa(line) + "] " + msg + lm.Msg = "[" + filename + ":" + strconv.Itoa(line) + "] " + lm.Msg } //set level info in front of filename info - if logLevel == levelLoggerImpl { + if lm.Level == levelLoggerImpl { // set to emergency to ensure all log will be print out correctly - logLevel = LevelEmergency + lm.Level = LevelEmergency } else { - msg = levelPrefix[logLevel] + " " + msg + lm.Msg = levelPrefix[lm.Level] + " " + lm.Msg } if bl.asynchronous { - lm := logMsgPool.Get().(*logMsg) - lm.level = logLevel - lm.msg = msg - lm.when = when + logM := logMsgPool.Get().(*LogMsg) + logM.Level = lm.Level + logM.Msg = lm.Msg + logM.When = lm.When if bl.outputs != nil { bl.msgChan <- lm } else { logMsgPool.Put(lm) } } else { - bl.writeToLoggers(when, msg, logLevel) + bl.writeToLoggers(lm) } return nil } @@ -345,7 +351,7 @@ func (bl *BeeLogger) startLogger() { for { select { case bm := <-bl.msgChan: - bl.writeToLoggers(bm.when, bm.msg, bm.level) + bl.writeToLoggers(bm) logMsgPool.Put(bm) case sg := <-bl.signalChan: // Now should only send "flush" or "close" to bl.signalChan @@ -370,7 +376,17 @@ func (bl *BeeLogger) Emergency(format string, v ...interface{}) { if LevelEmergency > bl.level { return } - bl.writeMsg(LevelEmergency, format, v...) + + lm := &LogMsg{ + Level: LevelEmergency, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Alert Log ALERT level message. @@ -378,7 +394,17 @@ func (bl *BeeLogger) Alert(format string, v ...interface{}) { if LevelAlert > bl.level { return } - bl.writeMsg(LevelAlert, format, v...) + + lm := &LogMsg{ + Level: LevelAlert, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Critical Log CRITICAL level message. @@ -386,7 +412,16 @@ func (bl *BeeLogger) Critical(format string, v ...interface{}) { if LevelCritical > bl.level { return } - bl.writeMsg(LevelCritical, format, v...) + lm := &LogMsg{ + Level: LevelCritical, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Error Log ERROR level message. @@ -394,7 +429,16 @@ func (bl *BeeLogger) Error(format string, v ...interface{}) { if LevelError > bl.level { return } - bl.writeMsg(LevelError, format, v...) + lm := &LogMsg{ + Level: LevelError, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Warning Log WARNING level message. @@ -402,7 +446,16 @@ func (bl *BeeLogger) Warning(format string, v ...interface{}) { if LevelWarn > bl.level { return } - bl.writeMsg(LevelWarn, format, v...) + lm := &LogMsg{ + Level: LevelWarn, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Notice Log NOTICE level message. @@ -410,7 +463,16 @@ func (bl *BeeLogger) Notice(format string, v ...interface{}) { if LevelNotice > bl.level { return } - bl.writeMsg(LevelNotice, format, v...) + lm := &LogMsg{ + Level: LevelNotice, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Informational Log INFORMATIONAL level message. @@ -418,7 +480,16 @@ func (bl *BeeLogger) Informational(format string, v ...interface{}) { if LevelInfo > bl.level { return } - bl.writeMsg(LevelInfo, format, v...) + lm := &LogMsg{ + Level: LevelInfo, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Debug Log DEBUG level message. @@ -426,7 +497,16 @@ func (bl *BeeLogger) Debug(format string, v ...interface{}) { if LevelDebug > bl.level { return } - bl.writeMsg(LevelDebug, format, v...) + lm := &LogMsg{ + Level: LevelDebug, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Warn Log WARN level message. @@ -435,7 +515,16 @@ func (bl *BeeLogger) Warn(format string, v ...interface{}) { if LevelWarn > bl.level { return } - bl.writeMsg(LevelWarn, format, v...) + lm := &LogMsg{ + Level: LevelWarn, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Info Log INFO level message. @@ -444,7 +533,16 @@ func (bl *BeeLogger) Info(format string, v ...interface{}) { if LevelInfo > bl.level { return } - bl.writeMsg(LevelInfo, format, v...) + lm := &LogMsg{ + Level: LevelInfo, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Trace Log TRACE level message. @@ -453,7 +551,16 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) { if LevelDebug > bl.level { return } - bl.writeMsg(LevelDebug, format, v...) + lm := &LogMsg{ + Level: LevelDebug, + Msg: format, + When: time.Now(), + } + if len(v) > 0 { + lm.Msg = fmt.Sprintf(lm.Msg, v...) + } + + bl.writeMsg(lm) } // Flush flush all chan data. @@ -497,7 +604,7 @@ func (bl *BeeLogger) flush() { for { if len(bl.msgChan) > 0 { bm := <-bl.msgChan - bl.writeToLoggers(bm.when, bm.msg, bm.level) + bl.writeToLoggers(bm) logMsgPool.Put(bm) continue } diff --git a/pkg/logs/logger.go b/pkg/logs/logger.go index a28bff6f..721c8dc1 100644 --- a/pkg/logs/logger.go +++ b/pkg/logs/logger.go @@ -30,10 +30,10 @@ func newLogWriter(wr io.Writer) *logWriter { return &logWriter{writer: wr} } -func (lg *logWriter) writeln(when time.Time, msg string) (int, error) { +func (lg *logWriter) writeln(lm *LogMsg) (int, error) { lg.Lock() - h, _, _ := formatTimeHeader(when) - n, err := lg.writer.Write(append(append(h, msg...), '\n')) + h, _, _ := formatTimeHeader(lm.When) + n, err := lg.writer.Write(append(append(h, lm.Msg...), '\n')) lg.Unlock() return n, err } diff --git a/pkg/logs/multifile.go b/pkg/logs/multifile.go index 90168274..1cd9e9f8 100644 --- a/pkg/logs/multifile.go +++ b/pkg/logs/multifile.go @@ -16,7 +16,6 @@ package logs import ( "encoding/json" - "time" ) // A filesLogWriter manages several fileLogWriter @@ -87,14 +86,14 @@ func (f *multiFileLogWriter) Destroy() { } } -func (f *multiFileLogWriter) WriteMsg(when time.Time, msg string, level int) error { +func (f *multiFileLogWriter) WriteMsg(lm *LogMsg) error { if f.fullLogWriter != nil { - f.fullLogWriter.WriteMsg(when, msg, level) + f.fullLogWriter.WriteMsg(lm) } for i := 0; i < len(f.writers)-1; i++ { if f.writers[i] != nil { - if level == f.writers[i].Level { - f.writers[i].WriteMsg(when, msg, level) + if lm.Level == f.writers[i].Level { + f.writers[i].WriteMsg(lm) } } } diff --git a/pkg/logs/slack.go b/pkg/logs/slack.go index e78eeab6..dad4f4ea 100644 --- a/pkg/logs/slack.go +++ b/pkg/logs/slack.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "net/url" - "time" ) // SLACKWriter implements beego LoggerInterface and is used to send jiaoliao webhook @@ -26,12 +25,12 @@ func (s *SLACKWriter) Init(jsonconfig string) error { // WriteMsg write message in smtp writer. // Sends an email with subject and only this message. -func (s *SLACKWriter) WriteMsg(when time.Time, msg string, level int) error { - if level > s.Level { +func (s *SLACKWriter) WriteMsg(lm *LogMsg) error { + if lm.Level > s.Level { return nil } - text := fmt.Sprintf("{\"text\": \"%s %s\"}", when.Format("2006-01-02 15:04:05"), msg) + text := fmt.Sprintf("{\"text\": \"%s %s\"}", lm.When.Format("2006-01-02 15:04:05"), lm.Msg) form := url.Values{} form.Add("payload", text) diff --git a/pkg/logs/smtp.go b/pkg/logs/smtp.go index 720c2d25..0d2b3c29 100644 --- a/pkg/logs/smtp.go +++ b/pkg/logs/smtp.go @@ -21,7 +21,6 @@ import ( "net" "net/smtp" "strings" - "time" ) // SMTPWriter implements LoggerInterface and is used to send emails via given SMTP-server. @@ -117,8 +116,8 @@ func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAd // WriteMsg writes message in smtp writer. // Sends an email with subject and only this message. -func (s *SMTPWriter) WriteMsg(when time.Time, msg string, level int) error { - if level > s.Level { +func (s *SMTPWriter) WriteMsg(lm *LogMsg) error { + if lm.Level > s.Level { return nil } @@ -131,7 +130,7 @@ func (s *SMTPWriter) WriteMsg(when time.Time, msg string, level int) error { // and send the email all in one step. contentType := "Content-Type: text/plain" + "; charset=UTF-8" mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.FromAddress + "<" + s.FromAddress + - ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", when.Format("2006-01-02 15:04:05")) + msg) + ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", lm.When.Format("2006-01-02 15:04:05")) + lm.Msg) return s.sendMail(s.Host, auth, s.FromAddress, s.RecipientAddresses, mailmsg) }