dip/vendor/github.com/gobuffalo/logger/formatter.go

155 lines
3.2 KiB
Go
Raw Normal View History

2020-01-26 16:38:57 +01:00
package logger
// I really don't want to have this, but until (if) https://github.com/sirupsen/logrus/pull/606 is merged we're stuck with all this code. And yes, this is ALL needed just to remove some blank space in the logs
import (
"bytes"
"fmt"
"sort"
"strings"
"sync"
"time"
"github.com/sirupsen/logrus"
)
const (
red = 31
yellow = 33
blue = 36
gray = 37
)
// textFormatter formats logs into text
type textFormatter struct {
ForceColors bool
isTerminal bool
sync.Once
}
func (f *textFormatter) init(entry *logrus.Entry) {
if entry.Logger != nil {
f.isTerminal = checkIfTerminal(entry.Logger.Out)
}
}
const defaultTimestampFormat = time.RFC3339
// Format renders a single log entry
func (f *textFormatter) Format(entry *logrus.Entry) ([]byte, error) {
prefixFieldClashes(entry.Data)
keys := make([]string, 0, len(entry.Data))
for k := range entry.Data {
keys = append(keys, k)
}
sort.Strings(keys)
var b *bytes.Buffer
if entry.Buffer != nil {
b = entry.Buffer
} else {
b = &bytes.Buffer{}
}
f.Do(func() { f.init(entry) })
isColored := (f.ForceColors || f.isTerminal)
if isColored {
f.printColored(b, entry, keys)
} else {
f.appendKeyValue(b, "level", entry.Level.String())
f.appendKeyValue(b, "time", entry.Time.Format(defaultTimestampFormat))
if entry.Message != "" {
f.appendKeyValue(b, "msg", entry.Message)
}
for _, key := range keys {
f.appendKeyValue(b, key, entry.Data[key])
}
}
b.WriteByte('\n')
return b.Bytes(), nil
}
func (f *textFormatter) printColored(b *bytes.Buffer, entry *logrus.Entry, keys []string) {
var levelColor int
switch entry.Level {
case logrus.DebugLevel:
levelColor = gray
case logrus.WarnLevel:
levelColor = yellow
case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
levelColor = red
default:
levelColor = blue
}
levelText := strings.ToUpper(entry.Level.String())[0:4]
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]", levelColor, levelText, entry.Time.Format(defaultTimestampFormat))
if entry.Message != "" {
fmt.Fprintf(b, " %s", entry.Message)
}
for _, k := range keys {
v := entry.Data[k]
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
f.appendValue(b, v)
}
}
func (f *textFormatter) needsQuoting(text string) bool {
if len(text) == 0 {
return true
}
for _, ch := range text {
if !((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') {
return true
}
}
return false
}
func (f *textFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
if b.Len() > 0 {
b.WriteByte(' ')
}
b.WriteString(key)
b.WriteByte('=')
f.appendValue(b, value)
}
func (f *textFormatter) appendValue(b *bytes.Buffer, value interface{}) {
stringVal, ok := value.(string)
if !ok {
stringVal = fmt.Sprint(value)
}
if !f.needsQuoting(stringVal) {
b.WriteString(stringVal)
} else {
b.WriteString(fmt.Sprintf("%q", stringVal))
}
}
func prefixFieldClashes(data logrus.Fields) {
if t, ok := data["time"]; ok {
data["fields.time"] = t
}
if m, ok := data["msg"]; ok {
data["fields.msg"] = m
}
if l, ok := data["level"]; ok {
data["fields.level"] = l
}
}