1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-24 04:20:55 +00:00

Merge pull request #4174 from IamCathal/custom-log-formatter-firstpr

Custom Log Formatter PR#1
This commit is contained in:
Ming Deng 2020-08-19 23:37:44 +08:00 committed by GitHub
commit 9003ca3eef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 222 additions and 96 deletions

View File

@ -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)
}

View File

@ -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
}
@ -115,7 +113,7 @@ func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error
if c.withMap {
// TopicLogGroup
strs := strings.SplitN(msg, Delimiter, 2)
strs := strings.SplitN(lm.Msg, Delimiter, 2)
if len(strs) == 2 {
pos := strings.LastIndex(strs[0], " ")
topic = strs[0][pos+1 : len(strs[0])]
@ -125,11 +123,11 @@ func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error
// send to empty Topic
if lg == nil {
content = msg
content = lm.Msg
lg = c.group[0]
}
} else {
content = msg
content = lm.Msg
lg = c.group[0]
}
@ -139,7 +137,7 @@ func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error
}
l := &Log{
Time: proto.Uint32(uint32(when.Unix())),
Time: proto.Uint32(uint32(lm.When.Unix())),
Contents: []*LogContent{
c1,
},

View File

@ -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
}

View File

@ -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
}

View File

@ -60,14 +60,14 @@ func (el *esLogger) Init(jsonconfig string) error {
}
// WriteMsg writes the msg and level into es
func (el *esLogger) WriteMsg(when time.Time, msg string, level int) error {
if level > el.Level {
func (el *esLogger) WriteMsg(lm *logs.LogMsg) error {
if lm.Level > el.Level {
return nil
}
idx := LogDocument{
Timestamp: when.Format(time.RFC3339),
Msg: msg,
Timestamp: lm.When.Format(time.RFC3339),
Msg: lm.Msg,
}
body, err := json.Marshal(idx)
@ -75,7 +75,7 @@ func (el *esLogger) WriteMsg(when time.Time, msg string, level int) error {
return err
}
req := esapi.IndexRequest{
Index: fmt.Sprintf("%04d.%02d.%02d", when.Year(), when.Month(), when.Day()),
Index: fmt.Sprintf("%04d.%02d.%02d", lm.When.Year(), lm.When.Month(), lm.When.Day()),
DocumentType: "logs",
Body: strings.NewReader(string(body)),
}

View File

@ -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

View File

@ -280,8 +280,13 @@ func testFileRotate(t *testing.T, fn1, fn2 string, daily, hourly bool) {
fw.hourlyOpenTime = time.Now().Add(-1 * time.Hour)
fw.hourlyOpenDate = fw.hourlyOpenTime.Day()
}
lm := &LogMsg{
Msg: "Test message",
Level: LevelDebug,
When: time.Now(),
}
fw.WriteMsg(time.Now(), "this is a msg for test", LevelDebug)
fw.WriteMsg(lm)
for _, file := range []string{fn1, fn2} {
_, err := os.Stat(file)

View File

@ -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)

View File

@ -39,7 +39,6 @@ import (
"os"
"path"
"runtime"
"strconv"
"strings"
"sync"
"time"
@ -86,7 +85,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()
}
@ -115,10 +114,11 @@ type BeeLogger struct {
init bool
enableFuncCallDepth bool
loggerFuncCallDepth int
enableFullFilePath bool
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,42 +273,52 @@ 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
var (
file string
line int
ok bool
)
when := time.Now()
if bl.enableFuncCallDepth {
_, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth)
_, file, line, ok = runtime.Caller(bl.loggerFuncCallDepth)
if !ok {
file = "???"
line = 0
}
_, filename := path.Split(file)
msg = "[" + filename + ":" + strconv.Itoa(line) + "] " + msg
if !bl.enableFullFilePath {
_, file = path.Split(file)
}
lm.FilePath = file
lm.LineNumber = line
lm.Msg = fmt.Sprintf("[%s:%d] %s", lm.FilePath, lm.LineNumber, 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 +362,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 +387,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 +405,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 +423,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 +440,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 +457,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 +474,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 +491,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 +508,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 +526,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 +544,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 +562,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 +615,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
}
@ -547,6 +665,12 @@ func GetLogger(prefixes ...string) *log.Logger {
return l
}
// EnableFullFilePath enables full file path logging. Disabled by default
// e.g "/home/Documents/GitHub/beego/mainapp/" instead of "mainapp"
func EnableFullFilePath(b bool) {
beeLogger.enableFullFilePath = b
}
// Reset will remove all the adapter
func Reset() {
beeLogger.Reset()

View File

@ -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
}

View File

@ -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)
}
}
}

View File

@ -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)

View File

@ -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)
}