fix: log panic when use nil error or stringer with Field method (#4130)

This commit is contained in:
Kevin Wan
2024-05-10 00:31:36 +08:00
committed by GitHub
parent 9d551d507f
commit 74331a45c9
4 changed files with 88 additions and 5 deletions

View File

@@ -6,6 +6,7 @@ import (
"log"
"os"
"path"
"reflect"
"runtime/debug"
"sync"
"sync/atomic"
@@ -153,11 +154,11 @@ func Errorw(msg string, fields ...LogField) {
func Field(key string, value any) LogField {
switch val := value.(type) {
case error:
return LogField{Key: key, Value: val.Error()}
return LogField{Key: key, Value: encodeError(val)}
case []error:
var errs []string
for _, err := range val {
errs = append(errs, err.Error())
errs = append(errs, encodeError(err))
}
return LogField{Key: key, Value: errs}
case time.Duration:
@@ -175,11 +176,11 @@ func Field(key string, value any) LogField {
}
return LogField{Key: key, Value: times}
case fmt.Stringer:
return LogField{Key: key, Value: val.String()}
return LogField{Key: key, Value: encodeStringer(val)}
case []fmt.Stringer:
var strs []string
for _, str := range val {
strs = append(strs, str.String())
strs = append(strs, encodeStringer(str))
}
return LogField{Key: key, Value: strs}
default:
@@ -414,6 +415,32 @@ func createOutput(path string) (io.WriteCloser, error) {
return NewLogger(path, rule, options.gzipEnabled)
}
func encodeError(err error) (ret string) {
return encodeWithRecover(err, func() string {
return err.Error()
})
}
func encodeStringer(v fmt.Stringer) (ret string) {
return encodeWithRecover(v, func() string {
return v.String()
})
}
func encodeWithRecover(arg any, fn func() string) (ret string) {
defer func() {
if err := recover(); err != nil {
if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
ret = nilAngleString
} else {
panic(err)
}
}
}()
return fn()
}
func getWriter() Writer {
w := writer.Load()
if w == nil {