fix race condition caused by writing to entry.Data, using the same technique as JSONFormatter

This commit is contained in:
Hǎi-Liàng "Hal" Wáng 2018-11-05 12:29:28 +00:00
parent 44067abb19
commit 2cafb78db2
2 changed files with 13 additions and 10 deletions

View File

@ -107,14 +107,17 @@ func (f *TextFormatter) isColored() bool {
// Format renders a single log entry // Format renders a single log entry
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
prefixFieldClashes(entry.Data, f.FieldMap, entry.HasCaller()) data := make(Fields)
for k, v := range entry.Data {
keys := make([]string, 0, len(entry.Data)) data[k] = v
for k := range entry.Data { }
prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
keys := make([]string, 0, len(data))
for k := range data {
keys = append(keys, k) keys = append(keys, k)
} }
fixedKeys := make([]string, 0, 4+len(entry.Data)) fixedKeys := make([]string, 0, 4+len(data))
if !f.DisableTimestamp { if !f.DisableTimestamp {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime)) fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime))
} }
@ -160,7 +163,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
timestampFormat = defaultTimestampFormat timestampFormat = defaultTimestampFormat
} }
if f.isColored() { if f.isColored() {
f.printColored(b, entry, keys, timestampFormat) f.printColored(b, entry, keys, nil, timestampFormat)
} else { } else {
for _, key := range fixedKeys { for _, key := range fixedKeys {
var value interface{} var value interface{}
@ -178,7 +181,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller(): case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller():
value = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) value = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
default: default:
value = entry.Data[key] value = data[key]
} }
f.appendKeyValue(b, key, value) f.appendKeyValue(b, key, value)
} }
@ -188,7 +191,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
return b.Bytes(), nil return b.Bytes(), nil
} }
func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields, timestampFormat string) {
var levelColor int var levelColor int
switch entry.Level { switch entry.Level {
case DebugLevel, TraceLevel: case DebugLevel, TraceLevel:
@ -225,7 +228,7 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message) fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message)
} }
for _, k := range keys { for _, k := range keys {
v := entry.Data[k] v := data[k]
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k) fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
f.appendValue(b, v) f.appendValue(b, v)
} }

View File

@ -144,7 +144,7 @@ func TestDisableLevelTruncation(t *testing.T) {
tf := &TextFormatter{DisableLevelTruncation: disabled} tf := &TextFormatter{DisableLevelTruncation: disabled}
var b bytes.Buffer var b bytes.Buffer
entry.Level = level entry.Level = level
tf.printColored(&b, entry, keys, timestampFormat) tf.printColored(&b, entry, keys, nil, timestampFormat)
logLine := (&b).String() logLine := (&b).String()
if disabled { if disabled {
expected := strings.ToUpper(level.String()) expected := strings.ToUpper(level.String())