forked from mirror/logrus
Add TextFormatter config for custom quote runes
This commit is contained in:
parent
cfca98e6d9
commit
b545aee819
|
@ -7,6 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -52,9 +53,13 @@ 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
|
||||||
|
QuoteRune rune
|
||||||
|
|
||||||
// Whether the logger's out is to a terminal
|
// Whether the logger's out is to a terminal
|
||||||
isTerminal bool
|
isTerminal bool
|
||||||
terminalOnce sync.Once
|
|
||||||
|
sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
||||||
|
@ -75,7 +80,10 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
||||||
|
|
||||||
prefixFieldClashes(entry.Data)
|
prefixFieldClashes(entry.Data)
|
||||||
|
|
||||||
f.terminalOnce.Do(func() {
|
f.Do(func() {
|
||||||
|
if f.QuoteRune == 0 || !utf8.ValidRune(f.QuoteRune) {
|
||||||
|
f.QuoteRune = '"'
|
||||||
|
}
|
||||||
if entry.Logger != nil {
|
if entry.Logger != nil {
|
||||||
f.isTerminal = IsTerminal(entry.Logger.Out)
|
f.isTerminal = IsTerminal(entry.Logger.Out)
|
||||||
}
|
}
|
||||||
|
@ -164,14 +172,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, "%q", value)
|
fmt.Fprintf(b, "%c%v%c", f.QuoteRune, value, f.QuoteRune)
|
||||||
}
|
}
|
||||||
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, "%q", errmsg)
|
fmt.Fprintf(b, "%c%v%c", f.QuoteRune, errmsg, f.QuoteRune)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
fmt.Fprint(b, value)
|
fmt.Fprint(b, value)
|
||||||
|
|
|
@ -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.Contains(b[idx+5:], []byte{'"'})
|
cont := bytes.ContainsRune(b[idx+5:], tf.QuoteRune)
|
||||||
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,6 +34,14 @@ 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.
|
||||||
|
tf.QuoteRune = '`'
|
||||||
|
checkQuoting(false, "")
|
||||||
|
checkQuoting(false, "abcd")
|
||||||
|
checkQuoting(true, "/foobar")
|
||||||
|
checkQuoting(true, errors.New("invalid argument"))
|
||||||
|
|
||||||
|
// Test for quoting empty fields.
|
||||||
tf.QuoteEmptyFields = true
|
tf.QuoteEmptyFields = true
|
||||||
checkQuoting(true, "")
|
checkQuoting(true, "")
|
||||||
}
|
}
|
||||||
|
@ -45,7 +53,8 @@ func TestTimestampFormat(t *testing.T) {
|
||||||
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 : 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]
|
timeStr = timeStr[1 : len(timeStr)-1]
|
||||||
}
|
}
|
||||||
if format == "" {
|
if format == "" {
|
||||||
|
|
Loading…
Reference in New Issue