forked from go-graphite/go-carbon
/
formatter.go
116 lines (100 loc) · 2.61 KB
/
formatter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package logging
import (
"bytes"
"fmt"
"sort"
"strings"
"github.com/Sirupsen/logrus"
)
// This is to not silently overwrite `time`, `msg` and `level` fields when
// dumping it. If this code wasn't there doing:
//
// logrus.WithField("level", 1).Info("hello")
//
// Would just silently drop the user provided level. Instead with this code
// it'll logged as:
//
// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
//
// It's not exported because it's still using Data in an opinionated way. It's to
// avoid code duplication between the two default formatters.
func prefixFieldClashes(data logrus.Fields) {
_, ok := data["time"]
if ok {
data["fields.time"] = data["time"]
}
_, ok = data["msg"]
if ok {
data["fields.msg"] = data["msg"]
}
_, ok = data["level"]
if ok {
data["fields.level"] = data["level"]
}
}
// TextFormatter копипаста logrus.TextFormatter с косметическими изменениями
type TextFormatter struct {
// // Set to true to bypass checking for a TTY before outputting colors.
// ForceColors bool
// DisableColors bool
// // Set to true to disable timestamp logging (useful when the output
// // is redirected to a logging system already adding a timestamp)
// DisableTimestamp bool
}
// Format returns formatted message text
func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) {
var keys []string
for k := range entry.Data {
keys = append(keys, k)
}
sort.Strings(keys)
b := &bytes.Buffer{}
prefixFieldClashes(entry.Data)
messagePrefix := fmt.Sprintf("%s ", strings.ToUpper(entry.Level.String())[0:1])
fmt.Fprintf(b, "[%s] %s%s",
entry.Time.Format("2006-01-02 15:04:05"),
messagePrefix,
entry.Message)
if len(keys) > 0 {
b.WriteString(" {")
for index, k := range keys {
if index > 0 {
b.WriteString(", ")
}
v := entry.Data[k]
fmt.Fprintf(b, "%s=%#v", k, v)
}
b.WriteString("}")
}
b.WriteString("\n")
return b.Bytes(), nil
}
func needsQuoting(text string) bool {
for _, ch := range text {
if !((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch < '9') ||
ch == '-' || ch == '.') {
return false
}
}
return true
}
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
switch value.(type) {
case string:
if needsQuoting(value.(string)) {
fmt.Fprintf(b, "%v=%s ", key, value)
} else {
fmt.Fprintf(b, "%v=%q ", key, value)
}
case error:
if needsQuoting(value.(error).Error()) {
fmt.Fprintf(b, "%v=%s ", key, value)
} else {
fmt.Fprintf(b, "%v=%q ", key, value)
}
default:
fmt.Fprintf(b, "%v=%v ", key, value)
}
}