12
// FieldMap allows customization of the key names for default fields.
13
type FieldMap map[fieldKey]string
15
func (f FieldMap) resolve(key fieldKey) string {
16
if k, ok := f[key]; ok {
23
// JSONFormatter formats logs into parsable json
24
type JSONFormatter struct {
25
// TimestampFormat sets the format used for marshaling timestamps.
26
// The format to use is the same than for time.Format or time.Parse from the standard
28
// The standard Library already provides a set of predefined format.
29
TimestampFormat string
31
// DisableTimestamp allows disabling automatic timestamps in output
34
// DisableHTMLEscape allows disabling html escaping in output
35
DisableHTMLEscape bool
37
// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
40
// FieldMap allows users to customize the names of keys for default fields.
42
// formatter := &JSONFormatter{
43
// FieldMap: FieldMap{
44
// FieldKeyTime: "@timestamp",
45
// FieldKeyLevel: "@level",
46
// FieldKeyMsg: "@message",
47
// FieldKeyFunc: "@caller",
52
// CallerPrettyfier can be set by the user to modify the content
53
// of the function and file keys in the json data when ReportCaller is
54
// activated. If any of the returned value is the empty string the
55
// corresponding key will be removed from json fields.
56
CallerPrettyfier func(*runtime.Frame) (function string, file string)
58
// PrettyPrint will indent all json logs
62
// Format renders a single log entry
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) {
68
// Otherwise errors are ignored by `encoding/json`
69
// https://github.com/sirupsen/logrus/issues/137
77
newData := make(Fields, 4)
78
newData[f.DataKey] = data
82
prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
84
timestampFormat := f.TimestampFormat
85
if timestampFormat == "" {
86
timestampFormat = defaultTimestampFormat
90
data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err
92
if !f.DisableTimestamp {
93
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
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)
104
data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
107
data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
112
if entry.Buffer != nil {
118
encoder := json.NewEncoder(b)
119
encoder.SetEscapeHTML(!f.DisableHTMLEscape)
121
encoder.SetIndent("", " ")
123
if err := encoder.Encode(data); err != nil {
124
return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err)
127
return b.Bytes(), nil