forked from mirror/logrus
Skip func type value in fields.
We skip those unprintable fields and an error field instead of dropping the whole trace. Fixes #642
This commit is contained in:
parent
a67f783a38
commit
7b467df697
14
entry.go
14
entry.go
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
@ -43,6 +44,9 @@ type Entry struct {
|
|||
|
||||
// When formatter is called in entry.log(), a Buffer may be set to entry
|
||||
Buffer *bytes.Buffer
|
||||
|
||||
// err may contain a field formatting error
|
||||
err string
|
||||
}
|
||||
|
||||
func NewEntry(logger *Logger) *Entry {
|
||||
|
@ -80,10 +84,18 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
|
|||
for k, v := range entry.Data {
|
||||
data[k] = v
|
||||
}
|
||||
var field_err string
|
||||
for k, v := range fields {
|
||||
if t := reflect.TypeOf(v); t != nil && t.Kind() == reflect.Func {
|
||||
field_err = fmt.Sprintf("can not add field %q", k)
|
||||
if entry.err != "" {
|
||||
field_err = entry.err + ", " + field_err
|
||||
}
|
||||
} else {
|
||||
data[k] = v
|
||||
}
|
||||
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time}
|
||||
}
|
||||
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: field_err}
|
||||
}
|
||||
|
||||
// Overrides the time of the Entry.
|
||||
|
|
15
formatter.go
15
formatter.go
|
@ -2,7 +2,14 @@ package logrus
|
|||
|
||||
import "time"
|
||||
|
||||
const defaultTimestampFormat = time.RFC3339
|
||||
// Default key names for the default fields
|
||||
const (
|
||||
defaultTimestampFormat = time.RFC3339
|
||||
FieldKeyMsg = "msg"
|
||||
FieldKeyLevel = "level"
|
||||
FieldKeyTime = "time"
|
||||
FieldKeyLogrusError = "logrus_error"
|
||||
)
|
||||
|
||||
// The Formatter interface is used to implement a custom Formatter. It takes an
|
||||
// `Entry`. It exposes all the fields, including the default ones:
|
||||
|
@ -48,4 +55,10 @@ func prefixFieldClashes(data Fields, fieldMap FieldMap) {
|
|||
data["fields."+levelKey] = l
|
||||
delete(data, levelKey)
|
||||
}
|
||||
|
||||
logrusErrKey := fieldMap.resolve(FieldKeyLogrusError)
|
||||
if l, ok := data[logrusErrKey]; ok {
|
||||
data["fields."+logrusErrKey] = l
|
||||
delete(data, logrusErrKey)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,6 @@ type fieldKey string
|
|||
// FieldMap allows customization of the key names for default fields.
|
||||
type FieldMap map[fieldKey]string
|
||||
|
||||
// Default key names for the default fields
|
||||
const (
|
||||
FieldKeyMsg = "msg"
|
||||
FieldKeyLevel = "level"
|
||||
FieldKeyTime = "time"
|
||||
)
|
||||
|
||||
func (f FieldMap) resolve(key fieldKey) string {
|
||||
if k, ok := f[key]; ok {
|
||||
return k
|
||||
|
@ -79,6 +72,9 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
|||
timestampFormat = defaultTimestampFormat
|
||||
}
|
||||
|
||||
if entry.err != "" {
|
||||
data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err
|
||||
}
|
||||
if !f.DisableTimestamp {
|
||||
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFieldValueError(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := &Logger{
|
||||
Out: buf,
|
||||
Formatter: new(JSONFormatter),
|
||||
Hooks: make(LevelHooks),
|
||||
Level: DebugLevel,
|
||||
}
|
||||
l.WithField("func", func() {}).Info("test")
|
||||
fmt.Println(buf.String())
|
||||
var data map[string]interface{}
|
||||
json.Unmarshal(buf.Bytes(), &data)
|
||||
_, ok := data[FieldKeyLogrusError]
|
||||
require.True(t, ok)
|
||||
}
|
||||
|
||||
func TestNoFieldValueError(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := &Logger{
|
||||
Out: buf,
|
||||
Formatter: new(JSONFormatter),
|
||||
Hooks: make(LevelHooks),
|
||||
Level: DebugLevel,
|
||||
}
|
||||
l.WithField("str", "str").Info("test")
|
||||
fmt.Println(buf.String())
|
||||
var data map[string]interface{}
|
||||
json.Unmarshal(buf.Bytes(), &data)
|
||||
_, ok := data[FieldKeyLogrusError]
|
||||
require.False(t, ok)
|
||||
}
|
|
@ -114,7 +114,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
|||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
fixedKeys := make([]string, 0, 3+len(entry.Data))
|
||||
fixedKeys := make([]string, 0, 4+len(entry.Data))
|
||||
if !f.DisableTimestamp {
|
||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime))
|
||||
}
|
||||
|
@ -122,6 +122,9 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
|||
if entry.Message != "" {
|
||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyMsg))
|
||||
}
|
||||
if entry.err != "" {
|
||||
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError))
|
||||
}
|
||||
|
||||
if !f.DisableSorting {
|
||||
if f.SortingFunc == nil {
|
||||
|
@ -164,6 +167,8 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
|||
value = entry.Level.String()
|
||||
case f.FieldMap.resolve(FieldKeyMsg):
|
||||
value = entry.Message
|
||||
case f.FieldMap.resolve(FieldKeyLogrusError):
|
||||
value = entry.err
|
||||
default:
|
||||
value = entry.Data[key]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue