|
@@ -16,8 +16,14 @@ const (
|
|
|
blue = 34
|
|
|
)
|
|
|
|
|
|
+var (
|
|
|
+ baseTimestamp time.Time
|
|
|
+ isTerminal bool
|
|
|
+)
|
|
|
+
|
|
|
func init() {
|
|
|
baseTimestamp = time.Now()
|
|
|
+ isTerminal = IsTerminal()
|
|
|
}
|
|
|
|
|
|
func miniTS() int {
|
|
@@ -31,45 +37,27 @@ type TextFormatter struct {
|
|
|
}
|
|
|
|
|
|
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
|
|
- b := &bytes.Buffer{}
|
|
|
-
|
|
|
- prefixFieldClashes(entry)
|
|
|
|
|
|
- if (f.ForceColors || IsTerminal()) && !f.DisableColors {
|
|
|
- levelText := strings.ToUpper(entry.Data["level"].(string))[0:4]
|
|
|
+ var keys []string
|
|
|
+ for k := range entry.Data {
|
|
|
+ keys = append(keys, k)
|
|
|
+ }
|
|
|
+ sort.Strings(keys)
|
|
|
|
|
|
- levelColor := blue
|
|
|
+ b := &bytes.Buffer{}
|
|
|
|
|
|
- if entry.Data["level"] == "warning" {
|
|
|
- levelColor = yellow
|
|
|
- } else if entry.Data["level"] == "error" ||
|
|
|
- entry.Data["level"] == "fatal" ||
|
|
|
- entry.Data["level"] == "panic" {
|
|
|
- levelColor = red
|
|
|
- }
|
|
|
+ prefixFieldClashes(entry)
|
|
|
|
|
|
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Data["msg"])
|
|
|
+ isColored := (f.ForceColors || isTerminal) && !f.DisableColors
|
|
|
|
|
|
- keys := make([]string, 0)
|
|
|
- for k, _ := range entry.Data {
|
|
|
- if k != "level" && k != "time" && k != "msg" {
|
|
|
- keys = append(keys, k)
|
|
|
- }
|
|
|
- }
|
|
|
- sort.Strings(keys)
|
|
|
- for _, k := range keys {
|
|
|
- v := entry.Data[k]
|
|
|
- fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
|
|
|
- }
|
|
|
+ if isColored {
|
|
|
+ printColored(b, entry, keys)
|
|
|
} else {
|
|
|
- f.AppendKeyValue(b, "time", entry.Data["time"].(string))
|
|
|
- f.AppendKeyValue(b, "level", entry.Data["level"].(string))
|
|
|
- f.AppendKeyValue(b, "msg", entry.Data["msg"].(string))
|
|
|
-
|
|
|
- for key, value := range entry.Data {
|
|
|
- if key != "time" && key != "level" && key != "msg" {
|
|
|
- f.AppendKeyValue(b, key, value)
|
|
|
- }
|
|
|
+ f.appendKeyValue(b, "time", entry.Time.Format(time.RFC3339))
|
|
|
+ f.appendKeyValue(b, "level", entry.Level.String())
|
|
|
+ f.appendKeyValue(b, "msg", entry.Message)
|
|
|
+ for _, key := range keys {
|
|
|
+ f.appendKeyValue(b, key, entry.Data[key])
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -77,10 +65,31 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
|
|
return b.Bytes(), nil
|
|
|
}
|
|
|
|
|
|
-func (f *TextFormatter) AppendKeyValue(b *bytes.Buffer, key, value interface{}) {
|
|
|
- if _, ok := value.(string); ok {
|
|
|
+func printColored(b *bytes.Buffer, entry *Entry, keys []string) {
|
|
|
+ var levelColor int
|
|
|
+ switch entry.Level {
|
|
|
+ case WarnLevel:
|
|
|
+ levelColor = yellow
|
|
|
+ case ErrorLevel, FatalLevel, PanicLevel:
|
|
|
+ levelColor = red
|
|
|
+ default:
|
|
|
+ levelColor = blue
|
|
|
+ }
|
|
|
+
|
|
|
+ levelText := strings.ToUpper(entry.Level.String())[0:4]
|
|
|
+
|
|
|
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
|
|
|
+ for _, k := range keys {
|
|
|
+ v := entry.Data[k]
|
|
|
+ fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
|
|
|
+ switch value.(type) {
|
|
|
+ case string, error:
|
|
|
fmt.Fprintf(b, "%v=%q ", key, value)
|
|
|
- } else {
|
|
|
+ default:
|
|
|
fmt.Fprintf(b, "%v=%v ", key, value)
|
|
|
}
|
|
|
}
|