Browse Source

feat: add log debug level (#2411)

MarkJoyMa 2 years ago
parent
commit
e6aa6fc361

+ 1 - 1
core/logx/config.go

@@ -7,7 +7,7 @@ type LogConf struct {
 	Encoding            string `json:",default=json,options=[json,plain]"`
 	TimeFormat          string `json:",optional"`
 	Path                string `json:",default=logs"`
-	Level               string `json:",default=info,options=[info,error,severe]"`
+	Level               string `json:",default=info,options=[debug,info,error,severe]"`
 	Compress            bool   `json:",optional"`
 	KeepDays            int    `json:",optional"`
 	StackCooldownMillis int    `json:",default=100"`

+ 8 - 0
core/logx/logger.go

@@ -7,6 +7,14 @@ import (
 
 // A Logger represents a logger.
 type Logger interface {
+	// Debug logs a message at info level.
+	Debug(...interface{})
+	// Debugf logs a message at info level.
+	Debugf(string, ...interface{})
+	// Debugv logs a message at info level.
+	Debugv(interface{})
+	// Debugw logs a message at info level.
+	Debugw(string, ...LogField)
 	// Error logs a message at error level.
 	Error(...interface{})
 	// Errorf logs a message at error level.

+ 28 - 0
core/logx/logs.go

@@ -64,6 +64,26 @@ func Close() error {
 	return nil
 }
 
+// Debug writes v into access log.
+func Debug(v ...interface{}) {
+	writeDebug(fmt.Sprint(v...))
+}
+
+// Debugf writes v with format into access log.
+func Debugf(format string, v ...interface{}) {
+	writeDebug(fmt.Sprintf(format, v...))
+}
+
+// Debugv writes v into access log with json content.
+func Debugv(v interface{}) {
+	writeDebug(v)
+}
+
+// Debugw writes msg along with fields into access log.
+func Debugw(msg string, fields ...LogField) {
+	writeDebug(msg, fields...)
+}
+
 // Disable disables the logging.
 func Disable() {
 	atomic.StoreUint32(&disableLog, 1)
@@ -352,6 +372,8 @@ func handleOptions(opts []LogOption) {
 
 func setupLogLevel(c LogConf) {
 	switch c.Level {
+	case levelDebug:
+		SetLevel(DebugLevel)
 	case levelInfo:
 		SetLevel(InfoLevel)
 	case levelError:
@@ -392,6 +414,12 @@ func shallLogStat() bool {
 	return atomic.LoadUint32(&disableStat) == 0
 }
 
+func writeDebug(val interface{}, fields ...LogField) {
+	if shallLog(DebugLevel) {
+		getWriter().Debug(val, addCaller(fields...)...)
+	}
+}
+
 func writeError(val interface{}, fields ...LogField) {
 	if shallLog(ErrorLevel) {
 		getWriter().Error(val, addCaller(fields...)...)

+ 46 - 0
core/logx/logs_test.go

@@ -35,6 +35,12 @@ func (mw *mockWriter) Alert(v interface{}) {
 	output(&mw.builder, levelAlert, v)
 }
 
+func (mw *mockWriter) Debug(v interface{}, fields ...LogField) {
+	mw.lock.Lock()
+	defer mw.lock.Unlock()
+	output(&mw.builder, levelDebug, v, fields...)
+}
+
 func (mw *mockWriter) Error(v interface{}, fields ...LogField) {
 	mw.lock.Lock()
 	defer mw.lock.Unlock()
@@ -212,6 +218,46 @@ func TestStructedLogAlert(t *testing.T) {
 	})
 }
 
+func TestStructedLogDebug(t *testing.T) {
+	w := new(mockWriter)
+	old := writer.Swap(w)
+	defer writer.Store(old)
+
+	doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
+		Debug(v...)
+	})
+}
+
+func TestStructedLogDebugf(t *testing.T) {
+	w := new(mockWriter)
+	old := writer.Swap(w)
+	defer writer.Store(old)
+
+	doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
+		Debugf(fmt.Sprint(v...))
+	})
+}
+
+func TestStructedLogDebugv(t *testing.T) {
+	w := new(mockWriter)
+	old := writer.Swap(w)
+	defer writer.Store(old)
+
+	doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
+		Debugv(fmt.Sprint(v...))
+	})
+}
+
+func TestStructedLogDebugw(t *testing.T) {
+	w := new(mockWriter)
+	old := writer.Swap(w)
+	defer writer.Store(old)
+
+	doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
+		Debugw(fmt.Sprint(v...), Field("foo", time.Second))
+	})
+}
+
 func TestStructedLogError(t *testing.T) {
 	w := new(mockWriter)
 	old := writer.Swap(w)

+ 22 - 0
core/logx/richlogger.go

@@ -40,6 +40,22 @@ type richLogger struct {
 	fields     []LogField
 }
 
+func (l *richLogger) Debug(v ...interface{}) {
+	l.debug(fmt.Sprint(v...))
+}
+
+func (l *richLogger) Debugf(format string, v ...interface{}) {
+	l.debug(fmt.Sprintf(format, v...))
+}
+
+func (l *richLogger) Debugv(v interface{}) {
+	l.debug(v)
+}
+
+func (l *richLogger) Debugw(msg string, fields ...LogField) {
+	l.debug(msg, fields...)
+}
+
 func (l *richLogger) Error(v ...interface{}) {
 	l.err(fmt.Sprint(v...))
 }
@@ -135,6 +151,12 @@ func (l *richLogger) buildFields(fields ...LogField) []LogField {
 	return fields
 }
 
+func (l *richLogger) debug(v interface{}, fields ...LogField) {
+	if shallLog(DebugLevel) {
+		getWriter().Debug(v, l.buildFields(fields...)...)
+	}
+}
+
 func (l *richLogger) err(v interface{}, fields ...LogField) {
 	if shallLog(ErrorLevel) {
 		getWriter().Error(v, l.buildFields(fields...)...)

+ 35 - 0
core/logx/richlogger_test.go

@@ -37,6 +37,41 @@ func TestTraceLog(t *testing.T) {
 	validate(t, w.String(), true, true)
 }
 
+func TestTraceDebug(t *testing.T) {
+	w := new(mockWriter)
+	old := writer.Swap(w)
+	writer.lock.RLock()
+	defer func() {
+		writer.lock.RUnlock()
+		writer.Store(old)
+	}()
+
+	otp := otel.GetTracerProvider()
+	tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
+	otel.SetTracerProvider(tp)
+	defer otel.SetTracerProvider(otp)
+
+	ctx, span := tp.Tracer("foo").Start(context.Background(), "bar")
+	defer span.End()
+
+	l := WithContext(ctx)
+	SetLevel(DebugLevel)
+	l.WithDuration(time.Second).Debug(testlog)
+	assert.True(t, strings.Contains(w.String(), traceKey))
+	assert.True(t, strings.Contains(w.String(), spanKey))
+	w.Reset()
+	l.WithDuration(time.Second).Debugf(testlog)
+	validate(t, w.String(), true, true)
+	w.Reset()
+	l.WithDuration(time.Second).Debugv(testlog)
+	validate(t, w.String(), true, true)
+	w.Reset()
+	l.WithDuration(time.Second).Debugw(testlog, Field("foo", "bar"))
+	validate(t, w.String(), true, true)
+	assert.True(t, strings.Contains(w.String(), "foo"), w.String())
+	assert.True(t, strings.Contains(w.String(), "bar"), w.String())
+}
+
 func TestTraceError(t *testing.T) {
 	w := new(mockWriter)
 	old := writer.Swap(w)

+ 5 - 2
core/logx/vars.go

@@ -3,8 +3,10 @@ package logx
 import "errors"
 
 const (
-	// InfoLevel logs everything
-	InfoLevel uint32 = iota
+	// DebugLevel logs everything
+	DebugLevel uint32 = iota
+	// InfoLevel does not include debugs
+	InfoLevel
 	// ErrorLevel includes errors, slows, stacks
 	ErrorLevel
 	// SevereLevel only log severe messages
@@ -37,6 +39,7 @@ const (
 	levelFatal  = "fatal"
 	levelSlow   = "slow"
 	levelStat   = "stat"
+	levelDebug  = "debug"
 
 	backupFileDelimiter = "-"
 	flags               = 0x0

+ 8 - 0
core/logx/writer.go

@@ -18,6 +18,7 @@ type (
 	Writer interface {
 		Alert(v interface{})
 		Close() error
+		Debug(v interface{}, fields ...LogField)
 		Error(v interface{}, fields ...LogField)
 		Info(v interface{}, fields ...LogField)
 		Severe(v interface{})
@@ -194,6 +195,10 @@ func (w *concreteWriter) Close() error {
 	return w.statLog.Close()
 }
 
+func (w *concreteWriter) Debug(v interface{}, fields ...LogField) {
+	output(w.infoLog, levelDebug, v, fields...)
+}
+
 func (w *concreteWriter) Error(v interface{}, fields ...LogField) {
 	output(w.errorLog, levelError, v, fields...)
 }
@@ -227,6 +232,9 @@ func (n nopWriter) Close() error {
 	return nil
 }
 
+func (n nopWriter) Debug(_ interface{}, _ ...LogField) {
+}
+
 func (n nopWriter) Error(_ interface{}, _ ...LogField) {
 }