forked from mirror/logrus
Have prefixFieldClashes respect the JSON FieldMap
Currently, it will fix clashes that don't exist and miss clashes that do exist due to field remapping. Fixes #708
This commit is contained in:
parent
8c0189d9f6
commit
efab7f37b7
17
formatter.go
17
formatter.go
|
@ -30,16 +30,19 @@ type Formatter interface {
|
|||
//
|
||||
// It's not exported because it's still using Data in an opinionated way. It's to
|
||||
// avoid code duplication between the two default formatters.
|
||||
func prefixFieldClashes(data Fields) {
|
||||
if t, ok := data["time"]; ok {
|
||||
data["fields.time"] = t
|
||||
func prefixFieldClashes(data Fields, fieldMap FieldMap) {
|
||||
timeKey := fieldMap.resolve(FieldKeyTime)
|
||||
if t, ok := data[timeKey]; ok {
|
||||
data["fields."+timeKey] = t
|
||||
}
|
||||
|
||||
if m, ok := data["msg"]; ok {
|
||||
data["fields.msg"] = m
|
||||
msgKey := fieldMap.resolve(FieldKeyMsg)
|
||||
if m, ok := data[msgKey]; ok {
|
||||
data["fields."+msgKey] = m
|
||||
}
|
||||
|
||||
if l, ok := data["level"]; ok {
|
||||
data["fields.level"] = l
|
||||
levelKey := fieldMap.resolve(FieldKeyLevel)
|
||||
if l, ok := data[levelKey]; ok {
|
||||
data["fields."+levelKey] = l
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
|||
data[k] = v
|
||||
}
|
||||
}
|
||||
prefixFieldClashes(data)
|
||||
prefixFieldClashes(data, f.FieldMap)
|
||||
|
||||
timestampFormat := f.TimestampFormat
|
||||
if timestampFormat == "" {
|
||||
|
|
|
@ -3,6 +3,7 @@ package logrus
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
@ -106,6 +107,60 @@ func TestFieldClashWithLevel(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFieldClashWithRemappedFields(t *testing.T) {
|
||||
formatter := &JSONFormatter{
|
||||
FieldMap: FieldMap{
|
||||
FieldKeyTime: "@timestamp",
|
||||
FieldKeyLevel: "@level",
|
||||
FieldKeyMsg: "@message",
|
||||
},
|
||||
}
|
||||
|
||||
b, err := formatter.Format(WithFields(Fields{
|
||||
"@timestamp": "@timestamp",
|
||||
"@level": "@level",
|
||||
"@message": "@message",
|
||||
"timestamp": "timestamp",
|
||||
"level": "level",
|
||||
"msg": "msg",
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
|
||||
entry := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &entry)
|
||||
if err != nil {
|
||||
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||
}
|
||||
|
||||
for _, field := range []string{"timestamp", "level", "msg"} {
|
||||
if entry[field] != field {
|
||||
t.Errorf("Expected field %v to be untouched; got %v", field, entry[field])
|
||||
}
|
||||
|
||||
remappedKey := fmt.Sprintf("fields.%s", field)
|
||||
if remapped, ok := entry[remappedKey]; ok {
|
||||
t.Errorf("Expected %s to be empty; got %v", remappedKey, remapped)
|
||||
}
|
||||
}
|
||||
|
||||
for _, field := range []string{"@timestamp", "@level", "@message"} {
|
||||
if entry[field] == field {
|
||||
t.Errorf("Expected field %v to be mapped to an Entry value", field)
|
||||
}
|
||||
|
||||
remappedKey := fmt.Sprintf("fields.%s", field)
|
||||
if remapped, ok := entry[remappedKey]; ok {
|
||||
if remapped != field {
|
||||
t.Errorf("Expected field %v to be copied to %s; got %v", field, remappedKey, remapped)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Expected field %v to be copied to %s; was absent", field, remappedKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONEntryEndsWithNewline(t *testing.T) {
|
||||
formatter := &JSONFormatter{}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ const (
|
|||
|
||||
var (
|
||||
baseTimestamp time.Time
|
||||
emptyFieldMap FieldMap
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -82,7 +83,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
|||
b = &bytes.Buffer{}
|
||||
}
|
||||
|
||||
prefixFieldClashes(entry.Data)
|
||||
prefixFieldClashes(entry.Data, emptyFieldMap)
|
||||
|
||||
f.Do(func() { f.init(entry) })
|
||||
|
||||
|
|
Loading…
Reference in New Issue