Address PR comments

This commit is contained in:
Ben Brooks 2017-02-15 13:08:26 +00:00
parent b545aee819
commit e98cd92ccf
No known key found for this signature in database
GPG Key ID: F2C8424D997DE166
2 changed files with 26 additions and 21 deletions

View File

@ -7,7 +7,6 @@ import (
"strings" "strings"
"sync" "sync"
"time" "time"
"unicode/utf8"
) )
const ( const (
@ -53,8 +52,9 @@ type TextFormatter struct {
// QuoteEmptyFields will wrap empty fields in quotes if true // QuoteEmptyFields will wrap empty fields in quotes if true
QuoteEmptyFields bool QuoteEmptyFields bool
// QuoteRune can be set to override the default quote style // QuoteCharacter can be set to the override the default quoting character "
QuoteRune rune // with something else. For example: ', or `.
QuoteCharacter string
// Whether the logger's out is to a terminal // Whether the logger's out is to a terminal
isTerminal bool isTerminal bool
@ -62,6 +62,15 @@ type TextFormatter struct {
sync.Once sync.Once
} }
func (f *TextFormatter) init(entry *Entry) {
if len(f.QuoteCharacter) == 0 {
f.QuoteCharacter = "\""
}
if entry.Logger != nil {
f.isTerminal = IsTerminal(entry.Logger.Out)
}
}
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
var b *bytes.Buffer var b *bytes.Buffer
keys := make([]string, 0, len(entry.Data)) keys := make([]string, 0, len(entry.Data))
@ -80,14 +89,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
prefixFieldClashes(entry.Data) prefixFieldClashes(entry.Data)
f.Do(func() { f.Do(func() { f.init(entry) })
if f.QuoteRune == 0 || !utf8.ValidRune(f.QuoteRune) {
f.QuoteRune = '"'
}
if entry.Logger != nil {
f.isTerminal = IsTerminal(entry.Logger.Out)
}
})
isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors
@ -172,14 +174,14 @@ func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
if !f.needsQuoting(value) { if !f.needsQuoting(value) {
b.WriteString(value) b.WriteString(value)
} else { } else {
fmt.Fprintf(b, "%c%v%c", f.QuoteRune, value, f.QuoteRune) fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, value, f.QuoteCharacter)
} }
case error: case error:
errmsg := value.Error() errmsg := value.Error()
if !f.needsQuoting(errmsg) { if !f.needsQuoting(errmsg) {
b.WriteString(errmsg) b.WriteString(errmsg)
} else { } else {
fmt.Fprintf(b, "%c%v%c", f.QuoteRune, errmsg, f.QuoteRune) fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, errmsg, f.QuoteCharacter)
} }
default: default:
fmt.Fprint(b, value) fmt.Fprint(b, value)

View File

@ -14,7 +14,7 @@ func TestQuoting(t *testing.T) {
checkQuoting := func(q bool, value interface{}) { checkQuoting := func(q bool, value interface{}) {
b, _ := tf.Format(WithField("test", value)) b, _ := tf.Format(WithField("test", value))
idx := bytes.Index(b, ([]byte)("test=")) idx := bytes.Index(b, ([]byte)("test="))
cont := bytes.ContainsRune(b[idx+5:], tf.QuoteRune) cont := bytes.Contains(b[idx+5:], []byte(tf.QuoteCharacter))
if cont != q { if cont != q {
if q { if q {
t.Errorf("quoting expected for: %#v", value) t.Errorf("quoting expected for: %#v", value)
@ -34,16 +34,23 @@ func TestQuoting(t *testing.T) {
checkQuoting(false, errors.New("invalid")) checkQuoting(false, errors.New("invalid"))
checkQuoting(true, errors.New("invalid argument")) checkQuoting(true, errors.New("invalid argument"))
// Test for custom quote rune. // Test for custom quote character.
tf.QuoteRune = '`' tf.QuoteCharacter = "`"
checkQuoting(false, "") checkQuoting(false, "")
checkQuoting(false, "abcd") checkQuoting(false, "abcd")
checkQuoting(true, "/foobar") checkQuoting(true, "/foobar")
checkQuoting(true, errors.New("invalid argument")) checkQuoting(true, errors.New("invalid argument"))
// Test for multi-character quotes.
tf.QuoteCharacter = "§~±"
checkQuoting(false, "abcd")
checkQuoting(true, errors.New("invalid argument"))
// Test for quoting empty fields. // Test for quoting empty fields.
tf.QuoteEmptyFields = true tf.QuoteEmptyFields = true
checkQuoting(true, "") checkQuoting(true, "")
checkQuoting(false, "abcd")
checkQuoting(true, errors.New("invalid argument"))
} }
func TestTimestampFormat(t *testing.T) { func TestTimestampFormat(t *testing.T) {
@ -52,11 +59,7 @@ func TestTimestampFormat(t *testing.T) {
customStr, _ := customFormatter.Format(WithField("test", "test")) customStr, _ := customFormatter.Format(WithField("test", "test"))
timeStart := bytes.Index(customStr, ([]byte)("time=")) timeStart := bytes.Index(customStr, ([]byte)("time="))
timeEnd := bytes.Index(customStr, ([]byte)("level=")) timeEnd := bytes.Index(customStr, ([]byte)("level="))
timeStr := customStr[timeStart+5 : timeEnd-1] timeStr := customStr[timeStart+5+len(customFormatter.QuoteCharacter) : timeEnd-1-len(customFormatter.QuoteCharacter)]
if timeStr[0] == byte(customFormatter.QuoteRune) &&
timeStr[len(timeStr)-1] == byte(customFormatter.QuoteRune) {
timeStr = timeStr[1 : len(timeStr)-1]
}
if format == "" { if format == "" {
format = time.RFC3339 format = time.RFC3339
} }