1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-22 06:40:55 +00:00

Add custom logging format functionality and global formatter functionality

This commit is contained in:
IamCathal 2020-08-24 20:22:38 +01:00
parent 09afe0ae8e
commit ed1d2c7f6e
8 changed files with 190 additions and 37 deletions

View File

@ -25,6 +25,8 @@ import (
type connWriter struct { type connWriter struct {
lg *logWriter lg *logWriter
innerWriter io.WriteCloser innerWriter io.WriteCloser
UseCustomFormatter bool
CustomFormatter func(*LogMsg) string
ReconnectOnMsg bool `json:"reconnectOnMsg"` ReconnectOnMsg bool `json:"reconnectOnMsg"`
Reconnect bool `json:"reconnect"` Reconnect bool `json:"reconnect"`
Net string `json:"net"` Net string `json:"net"`
@ -45,7 +47,14 @@ func (c *connWriter) Format(lm *LogMsg) string {
// Init initializes a connection writer with json config. // Init initializes a connection writer with json config.
// json config only needs they "level" key // json config only needs they "level" key
func (c *connWriter) Init(jsonConfig string) error { func (c *connWriter) Init(jsonConfig string, LogFormatter ...func(*LogMsg) string) error {
for _, elem := range LogFormatter {
if elem != nil {
c.UseCustomFormatter = true
c.CustomFormatter = elem
}
}
return json.Unmarshal([]byte(jsonConfig), c) return json.Unmarshal([]byte(jsonConfig), c)
} }

View File

@ -48,6 +48,8 @@ var colors = []brush{
// consoleWriter implements LoggerInterface and writes messages to terminal. // consoleWriter implements LoggerInterface and writes messages to terminal.
type consoleWriter struct { type consoleWriter struct {
lg *logWriter lg *logWriter
UseCustomFormatter bool
CustomFormatter func(*LogMsg) string
Level int `json:"level"` Level int `json:"level"`
Colorful bool `json:"color"` //this filed is useful only when system's terminal supports color Colorful bool `json:"color"` //this filed is useful only when system's terminal supports color
} }
@ -62,7 +64,7 @@ func (c *consoleWriter) Format(lm *LogMsg) string {
h, _, _ := formatTimeHeader(lm.When) h, _, _ := formatTimeHeader(lm.When)
bytes := append(append(h, msg...), '\n') bytes := append(append(h, msg...), '\n')
return "eee" + string(bytes) return string(bytes)
} }
@ -78,10 +80,18 @@ func NewConsole() Logger {
// Init initianlizes the console logger. // Init initianlizes the console logger.
// jsonConfig must be in the format '{"level":LevelTrace}' // jsonConfig must be in the format '{"level":LevelTrace}'
func (c *consoleWriter) Init(jsonConfig string) error { func (c *consoleWriter) Init(jsonConfig string, LogFormatter ...func(*LogMsg) string) error {
for _, elem := range LogFormatter {
if elem != nil {
c.UseCustomFormatter = true
c.CustomFormatter = elem
}
}
if len(jsonConfig) == 0 { if len(jsonConfig) == 0 {
return nil return nil
} }
return json.Unmarshal([]byte(jsonConfig), c) return json.Unmarshal([]byte(jsonConfig), c)
} }
@ -94,7 +104,15 @@ func (c *consoleWriter) WriteMsg(lm *LogMsg) error {
if c.Colorful { if c.Colorful {
lm.Msg = strings.Replace(lm.Msg, levelPrefix[lm.Level], colors[lm.Level](levelPrefix[lm.Level]), 1) lm.Msg = strings.Replace(lm.Msg, levelPrefix[lm.Level], colors[lm.Level](levelPrefix[lm.Level]), 1)
} }
msg := c.Format(lm)
msg := ""
if c.UseCustomFormatter {
msg = c.CustomFormatter(lm)
} else {
msg = c.Format(lm)
}
c.lg.writeln(msg) c.lg.writeln(msg)
return nil return nil
} }

View File

@ -60,6 +60,9 @@ type fileLogWriter struct {
hourlyOpenDate int hourlyOpenDate int
hourlyOpenTime time.Time hourlyOpenTime time.Time
UseCustomFormatter bool
CustomFormatter func(*LogMsg) string
Rotate bool `json:"rotate"` Rotate bool `json:"rotate"`
Level int `json:"level"` Level int `json:"level"`
@ -104,7 +107,14 @@ func (w *fileLogWriter) Format(lm *LogMsg) string {
// "rotate":true, // "rotate":true,
// "perm":"0600" // "perm":"0600"
// } // }
func (w *fileLogWriter) Init(jsonConfig string) error { func (w *fileLogWriter) Init(jsonConfig string, LogFormatter ...func(*LogMsg) string) error {
for _, elem := range LogFormatter {
if elem != nil {
w.UseCustomFormatter = true
w.CustomFormatter = elem
}
}
err := json.Unmarshal([]byte(jsonConfig), w) err := json.Unmarshal([]byte(jsonConfig), w)
if err != nil { if err != nil {
return err return err
@ -153,7 +163,13 @@ func (w *fileLogWriter) WriteMsg(lm *LogMsg) error {
return nil return nil
} }
hd, d, h := formatTimeHeader(lm.When) hd, d, h := formatTimeHeader(lm.When)
msg := w.Format(lm) msg := ""
if w.UseCustomFormatter {
msg = w.CustomFormatter(lm)
} else {
msg = w.Format(lm)
}
msg = fmt.Sprintf("%s %s\n", string(hd), msg) msg = fmt.Sprintf("%s %s\n", string(hd), msg)
if w.Rotate { if w.Rotate {
w.RLock() w.RLock()

View File

@ -15,6 +15,8 @@ type JLWriter struct {
RedirectURL string `json:"redirecturl,omitempty"` RedirectURL string `json:"redirecturl,omitempty"`
ImageURL string `json:"imageurl,omitempty"` ImageURL string `json:"imageurl,omitempty"`
Level int `json:"level"` Level int `json:"level"`
UseCustomFormatter bool
CustomFormatter func(*LogMsg) string
} }
// newJLWriter creates jiaoliao writer. // newJLWriter creates jiaoliao writer.
@ -23,7 +25,14 @@ func newJLWriter() Logger {
} }
// Init JLWriter with json config string // Init JLWriter with json config string
func (s *JLWriter) Init(jsonconfig string) error { func (s *JLWriter) Init(jsonconfig string, LogFormatter ...func(*LogMsg) string) error {
for _, elem := range LogFormatter {
if elem != nil {
s.UseCustomFormatter = true
s.CustomFormatter = elem
}
}
return json.Unmarshal([]byte(jsonconfig), s) return json.Unmarshal([]byte(jsonconfig), s)
} }

View File

@ -84,7 +84,7 @@ type newLoggerFunc func() Logger
// Logger defines the behavior of a log provider. // Logger defines the behavior of a log provider.
type Logger interface { type Logger interface {
Init(config string) error Init(config string, LogFormatter ...func(*LogMsg) string) error
WriteMsg(lm *LogMsg) error WriteMsg(lm *LogMsg) error
Format(lm *LogMsg) string Format(lm *LogMsg) string
Destroy() Destroy()
@ -115,6 +115,7 @@ type BeeLogger struct {
init bool init bool
enableFuncCallDepth bool enableFuncCallDepth bool
loggerFuncCallDepth int loggerFuncCallDepth int
globalFormatter func(*LogMsg) string
enableFullFilePath bool enableFullFilePath bool
asynchronous bool asynchronous bool
prefix string prefix string
@ -129,8 +130,6 @@ const defaultAsyncMsgLen = 1e3
type nameLogger struct { type nameLogger struct {
Logger Logger
// Formatter func(*LogMsg) string
LogFormatter
name string name string
} }
@ -206,7 +205,16 @@ func (bl *BeeLogger) setLogger(adapterName string, configs ...string) error {
} }
lg := logAdapter() lg := logAdapter()
err := lg.Init(config) var err error
// Global formatter overrides the default set formatter
// but not adapter specific formatters set with logs.SetLoggerWithOpts()
if bl.globalFormatter != nil {
err = lg.Init(config, bl.globalFormatter)
} else {
err = lg.Init(config)
}
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error()) fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error())
return err return err
@ -248,7 +256,6 @@ func (bl *BeeLogger) DelLogger(adapterName string) error {
func (bl *BeeLogger) writeToLoggers(lm *LogMsg) { func (bl *BeeLogger) writeToLoggers(lm *LogMsg) {
for _, l := range bl.outputs { for _, l := range bl.outputs {
// fmt.Println("Formatted: ", l.Format(lm))
err := l.WriteMsg(lm) err := l.WriteMsg(lm)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err) fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err)
@ -394,6 +401,74 @@ func (bl *BeeLogger) startLogger() {
} }
} }
// SetLoggerWithOpts sets a log adapter with a user defined logging format. Config must be valid JSON
// such as: {"interval":360}
func (bl *BeeLogger) setLoggerWithOpts(adapterName string, formatterFunc func(*LogMsg) string, configs ...string) error {
config := append(configs, "{}")[0]
for _, l := range bl.outputs {
if l.name == adapterName {
return fmt.Errorf("logs: duplicate adaptername %q (you have set this logger before)", adapterName)
}
}
logAdapter, ok := adapters[adapterName]
if !ok {
return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName)
}
if formatterFunc == nil {
return fmt.Errorf("No formatter set for %s log adapter", adapterName)
}
lg := logAdapter()
err := lg.Init(config, formatterFunc)
if err != nil {
fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error())
return err
}
bl.outputs = append(bl.outputs, &nameLogger{
name: adapterName,
Logger: lg,
})
return nil
}
// SetLogger provides a given logger adapter into BeeLogger with config string.
func (bl *BeeLogger) SetLoggerWithOpts(adapterName string, formatterFunc func(*LogMsg) string, configs ...string) error {
bl.lock.Lock()
defer bl.lock.Unlock()
if !bl.init {
bl.outputs = []*nameLogger{}
bl.init = true
}
return bl.setLoggerWithOpts(adapterName, formatterFunc, configs...)
}
// SetLoggerWIthOpts sets a given log adapter with a custom log adapter.
// Log Adapter must be given in the form common.SimpleKV{Key: "formatter": Value: struct.FormatFunc}
// where FormatFunc has the signature func(*LogMsg) string
func SetLoggerWithOpts(adapter string, config []string, formatterFunc func(*LogMsg) string) error {
err := beeLogger.SetLoggerWithOpts(adapter, formatterFunc, config...)
if err != nil {
log.Fatal(err)
}
return nil
}
func (bl *BeeLogger) setGlobalFormatter(fmtter func(*LogMsg) string) error {
bl.globalFormatter = fmtter
return nil
}
// SetGlobalFormatter sets the global formatter for all log adapters
// This overrides and other individually set adapter
func SetGlobalFormatter(fmtter func(*LogMsg) string) error {
return beeLogger.setGlobalFormatter(fmtter)
}
// Emergency Log EMERGENCY level message. // Emergency Log EMERGENCY level message.
func (bl *BeeLogger) Emergency(format string, v ...interface{}) { func (bl *BeeLogger) Emergency(format string, v ...interface{}) {
if LevelEmergency > bl.level { if LevelEmergency > bl.level {

View File

@ -27,6 +27,8 @@ type multiFileLogWriter struct {
writers [LevelDebug + 1 + 1]*fileLogWriter // the last one for fullLogWriter writers [LevelDebug + 1 + 1]*fileLogWriter // the last one for fullLogWriter
fullLogWriter *fileLogWriter fullLogWriter *fileLogWriter
Separate []string `json:"separate"` Separate []string `json:"separate"`
UseCustomFormatter bool
CustomFormatter func(*LogMsg) string
} }
var levelNames = [...]string{"emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"} var levelNames = [...]string{"emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"}
@ -44,7 +46,14 @@ var levelNames = [...]string{"emergency", "alert", "critical", "error", "warning
// "separate":["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"], // "separate":["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"],
// } // }
func (f *multiFileLogWriter) Init(config string) error { func (f *multiFileLogWriter) Init(config string, LogFormatter ...func(*LogMsg) string) error {
for _, elem := range LogFormatter {
if elem != nil {
f.UseCustomFormatter = true
f.CustomFormatter = elem
}
}
writer := newFileWriter().(*fileLogWriter) writer := newFileWriter().(*fileLogWriter)
err := writer.Init(config) err := writer.Init(config)
if err != nil { if err != nil {
@ -74,7 +83,6 @@ func (f *multiFileLogWriter) Init(config string) error {
} }
} }
} }
return nil return nil
} }

View File

@ -11,6 +11,8 @@ import (
type SLACKWriter struct { type SLACKWriter struct {
WebhookURL string `json:"webhookurl"` WebhookURL string `json:"webhookurl"`
Level int `json:"level"` Level int `json:"level"`
UseCustomFormatter bool
CustomFormatter func(*LogMsg) string
} }
// newSLACKWriter creates jiaoliao writer. // newSLACKWriter creates jiaoliao writer.
@ -23,7 +25,14 @@ func (s *SLACKWriter) Format(lm *LogMsg) string {
} }
// Init SLACKWriter with json config string // Init SLACKWriter with json config string
func (s *SLACKWriter) Init(jsonconfig string) error { func (s *SLACKWriter) Init(jsonconfig string, LogFormatter ...func(*LogMsg) string) error {
for _, elem := range LogFormatter {
if elem != nil {
s.UseCustomFormatter = true
s.CustomFormatter = elem
}
}
return json.Unmarshal([]byte(jsonconfig), s) return json.Unmarshal([]byte(jsonconfig), s)
} }

View File

@ -32,6 +32,8 @@ type SMTPWriter struct {
FromAddress string `json:"fromAddress"` FromAddress string `json:"fromAddress"`
RecipientAddresses []string `json:"sendTos"` RecipientAddresses []string `json:"sendTos"`
Level int `json:"level"` Level int `json:"level"`
UseCustomFormatter bool
CustomFormatter func(*LogMsg) string
} }
// NewSMTPWriter creates the smtp writer. // NewSMTPWriter creates the smtp writer.
@ -50,7 +52,14 @@ func newSMTPWriter() Logger {
// "sendTos":["email1","email2"], // "sendTos":["email1","email2"],
// "level":LevelError // "level":LevelError
// } // }
func (s *SMTPWriter) Init(jsonconfig string) error { func (s *SMTPWriter) Init(jsonconfig string, LogFormatter ...func(*LogMsg) string) error {
for _, elem := range LogFormatter {
if elem != nil {
s.UseCustomFormatter = true
s.CustomFormatter = elem
}
}
return json.Unmarshal([]byte(jsonconfig), s) return json.Unmarshal([]byte(jsonconfig), s)
} }