Add TextFormatter config for custom quote runes

This commit is contained in:
Ben Brooks 2017-02-14 11:51:23 +00:00
parent cfca98e6d9
commit b545aee819
No known key found for this signature in database
GPG Key ID: F2C8424D997DE166
2 changed files with 24 additions and 7 deletions

View File

@ -7,6 +7,7 @@ import (
"strings"
"sync"
"time"
"unicode/utf8"
)
const (
@ -52,9 +53,13 @@ type TextFormatter struct {
// QuoteEmptyFields will wrap empty fields in quotes if true
QuoteEmptyFields bool
// QuoteRune can be set to override the default quote style
QuoteRune rune
// Whether the logger's out is to a terminal
isTerminal bool
terminalOnce sync.Once
isTerminal bool
sync.Once
}
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
@ -75,7 +80,10 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
prefixFieldClashes(entry.Data)
f.terminalOnce.Do(func() {
f.Do(func() {
if f.QuoteRune == 0 || !utf8.ValidRune(f.QuoteRune) {
f.QuoteRune = '"'
}
if entry.Logger != nil {
f.isTerminal = IsTerminal(entry.Logger.Out)
}
@ -164,14 +172,14 @@ func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
if !f.needsQuoting(value) {
b.WriteString(value)
} else {
fmt.Fprintf(b, "%q", value)
fmt.Fprintf(b, "%c%v%c", f.QuoteRune, value, f.QuoteRune)
}
case error:
errmsg := value.Error()
if !f.needsQuoting(errmsg) {
b.WriteString(errmsg)
} else {
fmt.Fprintf(b, "%q", errmsg)
fmt.Fprintf(b, "%c%v%c", f.QuoteRune, errmsg, f.QuoteRune)
}
default:
fmt.Fprint(b, value)

View File

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