...
1 package logrus
2
3 import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "runtime"
8 )
9
10 type fieldKey string
11
12
13 type FieldMap map[fieldKey]string
14
15 func (f FieldMap) resolve(key fieldKey) string {
16 if k, ok := f[key]; ok {
17 return k
18 }
19
20 return string(key)
21 }
22
23
24 type JSONFormatter struct {
25
26
27
28
29 TimestampFormat string
30
31
32 DisableTimestamp bool
33
34
35 DisableHTMLEscape bool
36
37
38 DataKey string
39
40
41
42
43
44
45
46
47
48
49
50 FieldMap FieldMap
51
52
53
54
55
56 CallerPrettyfier func(*runtime.Frame) (function string, file string)
57
58
59 PrettyPrint bool
60 }
61
62
63 func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
64 data := make(Fields, len(entry.Data)+4)
65 for k, v := range entry.Data {
66 switch v := v.(type) {
67 case error:
68
69
70 data[k] = v.Error()
71 default:
72 data[k] = v
73 }
74 }
75
76 if f.DataKey != "" {
77 newData := make(Fields, 4)
78 newData[f.DataKey] = data
79 data = newData
80 }
81
82 prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
83
84 timestampFormat := f.TimestampFormat
85 if timestampFormat == "" {
86 timestampFormat = defaultTimestampFormat
87 }
88
89 if entry.err != "" {
90 data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err
91 }
92 if !f.DisableTimestamp {
93 data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
94 }
95 data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
96 data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
97 if entry.HasCaller() {
98 funcVal := entry.Caller.Function
99 fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
100 if f.CallerPrettyfier != nil {
101 funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
102 }
103 if funcVal != "" {
104 data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
105 }
106 if fileVal != "" {
107 data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
108 }
109 }
110
111 var b *bytes.Buffer
112 if entry.Buffer != nil {
113 b = entry.Buffer
114 } else {
115 b = &bytes.Buffer{}
116 }
117
118 encoder := json.NewEncoder(b)
119 encoder.SetEscapeHTML(!f.DisableHTMLEscape)
120 if f.PrettyPrint {
121 encoder.SetIndent("", " ")
122 }
123 if err := encoder.Encode(data); err != nil {
124 return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err)
125 }
126
127 return b.Bytes(), nil
128 }
129
View as plain text