From fbf2eebc42ecba3e4dcccfc2004cff8ad7068304 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Fri, 13 Aug 2021 18:28:39 +0800 Subject: [PATCH] add Errorv/Infov/Slowv (#909) --- core/logx/durationlogger.go | 24 +++++++-- core/logx/logs.go | 100 ++++++++++++++++++++++++++---------- core/logx/logs_test.go | 52 ++++++++++++++++++- core/logx/syslog_test.go | 2 +- core/logx/tracelogger.go | 22 +++++++- 5 files changed, 166 insertions(+), 34 deletions(-) diff --git a/core/logx/durationlogger.go b/core/logx/durationlogger.go index 4979f7e7..d55af95f 100644 --- a/core/logx/durationlogger.go +++ b/core/logx/durationlogger.go @@ -31,6 +31,12 @@ func (l *durationLogger) Errorf(format string, v ...interface{}) { } } +func (l *durationLogger) Errorv(v interface{}) { + if shallLog(ErrorLevel) { + l.write(errorLog, levelError, v) + } +} + func (l *durationLogger) Info(v ...interface{}) { if shallLog(InfoLevel) { l.write(infoLog, levelInfo, fmt.Sprint(v...)) @@ -43,6 +49,12 @@ func (l *durationLogger) Infof(format string, v ...interface{}) { } } +func (l *durationLogger) Infov(v interface{}) { + if shallLog(InfoLevel) { + l.write(infoLog, levelInfo, v) + } +} + func (l *durationLogger) Slow(v ...interface{}) { if shallLog(ErrorLevel) { l.write(slowLog, levelSlow, fmt.Sprint(v...)) @@ -55,14 +67,20 @@ func (l *durationLogger) Slowf(format string, v ...interface{}) { } } +func (l *durationLogger) Slowv(v interface{}) { + if shallLog(ErrorLevel) { + l.write(slowLog, levelSlow, v) + } +} + func (l *durationLogger) WithDuration(duration time.Duration) Logger { l.Duration = timex.ReprOfDuration(duration) return l } -func (l *durationLogger) write(writer io.Writer, level, content string) { +func (l *durationLogger) write(writer io.Writer, level string, val interface{}) { l.Timestamp = getTimestamp() l.Level = level - l.Content = content - outputJson(writer, logEntry(*l)) + l.Content = val + outputJson(writer, l) } diff --git a/core/logx/logs.go b/core/logx/logs.go index 068ce0a3..81f23401 100644 --- a/core/logx/logs.go +++ b/core/logx/logs.go @@ -81,10 +81,10 @@ var ( type ( logEntry struct { - Timestamp string `json:"@timestamp"` - Level string `json:"level"` - Duration string `json:"duration,omitempty"` - Content string `json:"content"` + Timestamp string `json:"@timestamp"` + Level string `json:"level"` + Duration string `json:"duration,omitempty"` + Content interface{} `json:"content"` } logOptions struct { @@ -100,10 +100,13 @@ type ( Logger interface { Error(...interface{}) Errorf(string, ...interface{}) + Errorv(interface{}) Info(...interface{}) Infof(string, ...interface{}) + Infov(interface{}) Slow(...interface{}) Slowf(string, ...interface{}) + Slowv(interface{}) WithDuration(time.Duration) Logger } ) @@ -135,7 +138,7 @@ func SetUp(c LogConf) error { // Alert alerts v in alert level, and the message is written to error log. func Alert(v string) { - output(errorLog, levelAlert, v) + outputText(errorLog, levelAlert, v) } // Close closes the logging. @@ -207,19 +210,19 @@ func Error(v ...interface{}) { ErrorCaller(1, v...) } -// Errorf writes v with format into error log. -func Errorf(format string, v ...interface{}) { - ErrorCallerf(1, format, v...) -} - // ErrorCaller writes v with context into error log. func ErrorCaller(callDepth int, v ...interface{}) { - errorSync(fmt.Sprint(v...), callDepth+callerInnerDepth) + errorTextSync(fmt.Sprint(v...), callDepth+callerInnerDepth) } // ErrorCallerf writes v with context in format into error log. func ErrorCallerf(callDepth int, format string, v ...interface{}) { - errorSync(fmt.Sprintf(format, v...), callDepth+callerInnerDepth) + errorTextSync(fmt.Sprintf(format, v...), callDepth+callerInnerDepth) +} + +// Errorf writes v with format into error log. +func Errorf(format string, v ...interface{}) { + ErrorCallerf(1, format, v...) } // ErrorStack writes v along with call stack into error log. @@ -234,14 +237,25 @@ func ErrorStackf(format string, v ...interface{}) { stackSync(fmt.Sprintf(format, v...)) } +// Errorv writes v into error log with json content. +// No call stack attached, because not elegant to pack the messages. +func Errorv(v interface{}) { + errorAnySync(v) +} + // Info writes v into access log. func Info(v ...interface{}) { - infoSync(fmt.Sprint(v...)) + infoTextSync(fmt.Sprint(v...)) } // Infof writes v with format into access log. func Infof(format string, v ...interface{}) { - infoSync(fmt.Sprintf(format, v...)) + infoTextSync(fmt.Sprintf(format, v...)) +} + +// Infov writes v into access log with json content. +func Infov(v interface{}) { + infoAnySync(v) } // Must checks if err is nil, otherwise logs the err and exits. @@ -249,7 +263,7 @@ func Must(err error) { if err != nil { msg := formatWithCaller(err.Error(), 3) log.Print(msg) - output(severeLog, levelFatal, msg) + outputText(severeLog, levelFatal, msg) os.Exit(1) } } @@ -271,12 +285,17 @@ func Severef(format string, v ...interface{}) { // Slow writes v into slow log. func Slow(v ...interface{}) { - slowSync(fmt.Sprint(v...)) + slowTextSync(fmt.Sprint(v...)) } // Slowf writes v with format into slow log. func Slowf(format string, v ...interface{}) { - slowSync(fmt.Sprintf(format, v...)) + slowTextSync(fmt.Sprintf(format, v...)) +} + +// Slowv writes v into slow log with json content. +func Slowv(v interface{}) { + slowAnySync(v) } // Stat writes v into stat log. @@ -319,7 +338,13 @@ func createOutput(path string) (io.WriteCloser, error) { options.gzipEnabled), options.gzipEnabled) } -func errorSync(msg string, callDepth int) { +func errorAnySync(v interface{}) { + if shallLog(ErrorLevel) { + outputAny(errorLog, levelError, v) + } +} + +func errorTextSync(msg string, callDepth int) { if shallLog(ErrorLevel) { outputError(errorLog, msg, callDepth) } @@ -369,13 +394,28 @@ func handleOptions(opts []LogOption) { } } -func infoSync(msg string) { +func infoAnySync(val interface{}) { if shallLog(InfoLevel) { - output(infoLog, levelInfo, msg) + outputAny(infoLog, levelInfo, val) } } -func output(writer io.Writer, level, msg string) { +func infoTextSync(msg string) { + if shallLog(InfoLevel) { + outputText(infoLog, levelInfo, msg) + } +} + +func outputAny(writer io.Writer, level string, val interface{}) { + info := logEntry{ + Timestamp: getTimestamp(), + Level: level, + Content: val, + } + outputJson(writer, info) +} + +func outputText(writer io.Writer, level, msg string) { info := logEntry{ Timestamp: getTimestamp(), Level: level, @@ -386,7 +426,7 @@ func output(writer io.Writer, level, msg string) { func outputError(writer io.Writer, msg string, callDepth int) { content := formatWithCaller(msg, callDepth) - output(writer, levelError, content) + outputText(writer, levelError, content) } func outputJson(writer io.Writer, info interface{}) { @@ -489,7 +529,7 @@ func setupWithVolume(c LogConf) error { func severeSync(msg string) { if shallLog(SevereLevel) { - output(severeLog, levelSevere, fmt.Sprintf("%s\n%s", msg, string(debug.Stack()))) + outputText(severeLog, levelSevere, fmt.Sprintf("%s\n%s", msg, string(debug.Stack()))) } } @@ -501,21 +541,27 @@ func shallLogStat() bool { return atomic.LoadUint32(&disableStat) == 0 } -func slowSync(msg string) { +func slowAnySync(v interface{}) { if shallLog(ErrorLevel) { - output(slowLog, levelSlow, msg) + outputAny(slowLog, levelSlow, v) + } +} + +func slowTextSync(msg string) { + if shallLog(ErrorLevel) { + outputText(slowLog, levelSlow, msg) } } func stackSync(msg string) { if shallLog(ErrorLevel) { - output(stackLog, levelError, fmt.Sprintf("%s\n%s", msg, string(debug.Stack()))) + outputText(stackLog, levelError, fmt.Sprintf("%s\n%s", msg, string(debug.Stack()))) } } func statSync(msg string) { if shallLogStat() && shallLog(InfoLevel) { - output(statLog, levelStat, msg) + outputText(statLog, levelStat, msg) } } diff --git a/core/logx/logs_test.go b/core/logx/logs_test.go index 5db9ef14..cd3f37f5 100644 --- a/core/logx/logs_test.go +++ b/core/logx/logs_test.go @@ -92,6 +92,30 @@ func TestStructedLogAlert(t *testing.T) { }) } +func TestStructedLogError(t *testing.T) { + doTestStructedLog(t, levelError, func(writer io.WriteCloser) { + errorLog = writer + }, func(v ...interface{}) { + Error(v...) + }) +} + +func TestStructedLogErrorf(t *testing.T) { + doTestStructedLog(t, levelError, func(writer io.WriteCloser) { + errorLog = writer + }, func(v ...interface{}) { + Errorf("%s", fmt.Sprint(v...)) + }) +} + +func TestStructedLogErrorv(t *testing.T) { + doTestStructedLog(t, levelError, func(writer io.WriteCloser) { + errorLog = writer + }, func(v ...interface{}) { + Errorv(fmt.Sprint(v...)) + }) +} + func TestStructedLogInfo(t *testing.T) { doTestStructedLog(t, levelInfo, func(writer io.WriteCloser) { infoLog = writer @@ -100,6 +124,22 @@ func TestStructedLogInfo(t *testing.T) { }) } +func TestStructedLogInfof(t *testing.T) { + doTestStructedLog(t, levelInfo, func(writer io.WriteCloser) { + infoLog = writer + }, func(v ...interface{}) { + Infof("%s", fmt.Sprint(v...)) + }) +} + +func TestStructedLogInfov(t *testing.T) { + doTestStructedLog(t, levelInfo, func(writer io.WriteCloser) { + infoLog = writer + }, func(v ...interface{}) { + Infov(fmt.Sprint(v...)) + }) +} + func TestStructedLogSlow(t *testing.T) { doTestStructedLog(t, levelSlow, func(writer io.WriteCloser) { slowLog = writer @@ -116,6 +156,14 @@ func TestStructedLogSlowf(t *testing.T) { }) } +func TestStructedLogSlowv(t *testing.T) { + doTestStructedLog(t, levelSlow, func(writer io.WriteCloser) { + slowLog = writer + }, func(v ...interface{}) { + Slowv(fmt.Sprint(v...)) + }) +} + func TestStructedLogStat(t *testing.T) { doTestStructedLog(t, levelStat, func(writer io.WriteCloser) { statLog = writer @@ -368,7 +416,9 @@ func doTestStructedLog(t *testing.T, level string, setup func(writer io.WriteClo t.Error(err) } assert.Equal(t, level, entry.Level) - assert.True(t, strings.Contains(entry.Content, message)) + val, ok := entry.Content.(string) + assert.True(t, ok) + assert.True(t, strings.Contains(val, message)) } func testSetLevelTwiceWithMode(t *testing.T, mode string) { diff --git a/core/logx/syslog_test.go b/core/logx/syslog_test.go index 2b934a97..01b285ee 100644 --- a/core/logx/syslog_test.go +++ b/core/logx/syslog_test.go @@ -44,5 +44,5 @@ func captureOutput(f func()) string { func getContent(jsonStr string) string { var entry logEntry json.Unmarshal([]byte(jsonStr), &entry) - return entry.Content + return entry.Content.(string) } diff --git a/core/logx/tracelogger.go b/core/logx/tracelogger.go index af305ee7..1aba7158 100644 --- a/core/logx/tracelogger.go +++ b/core/logx/tracelogger.go @@ -29,6 +29,12 @@ func (l *traceLogger) Errorf(format string, v ...interface{}) { } } +func (l *traceLogger) Errorv(v interface{}) { + if shallLog(ErrorLevel) { + l.write(errorLog, levelError, v) + } +} + func (l *traceLogger) Info(v ...interface{}) { if shallLog(InfoLevel) { l.write(infoLog, levelInfo, fmt.Sprint(v...)) @@ -41,6 +47,12 @@ func (l *traceLogger) Infof(format string, v ...interface{}) { } } +func (l *traceLogger) Infov(v interface{}) { + if shallLog(InfoLevel) { + l.write(infoLog, levelInfo, v) + } +} + func (l *traceLogger) Slow(v ...interface{}) { if shallLog(ErrorLevel) { l.write(slowLog, levelSlow, fmt.Sprint(v...)) @@ -53,15 +65,21 @@ func (l *traceLogger) Slowf(format string, v ...interface{}) { } } +func (l *traceLogger) Slowv(v interface{}) { + if shallLog(ErrorLevel) { + l.write(slowLog, levelSlow, v) + } +} + func (l *traceLogger) WithDuration(duration time.Duration) Logger { l.Duration = timex.ReprOfDuration(duration) return l } -func (l *traceLogger) write(writer io.Writer, level, content string) { +func (l *traceLogger) write(writer io.Writer, level string, val interface{}) { l.Timestamp = getTimestamp() l.Level = level - l.Content = content + l.Content = val l.Trace = traceIdFromContext(l.ctx) l.Span = spanIdFromContext(l.ctx) outputJson(writer, l)