blob: e787ea17506a7d126d954b0fb8aa4944f240ff1a [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001package logrus
2
3import (
4 "encoding/json"
5 "fmt"
6)
7
8type fieldKey string
9type FieldMap map[fieldKey]string
10
11const (
12 FieldKeyMsg = "msg"
13 FieldKeyLevel = "level"
14 FieldKeyTime = "time"
15)
16
17func (f FieldMap) resolve(key fieldKey) string {
18 if k, ok := f[key]; ok {
19 return k
20 }
21
22 return string(key)
23}
24
25type JSONFormatter struct {
26 // TimestampFormat sets the format used for marshaling timestamps.
27 TimestampFormat string
28
29 // DisableTimestamp allows disabling automatic timestamps in output
30 DisableTimestamp bool
31
32 // FieldMap allows users to customize the names of keys for various fields.
33 // As an example:
34 // formatter := &JSONFormatter{
35 // FieldMap: FieldMap{
36 // FieldKeyTime: "@timestamp",
37 // FieldKeyLevel: "@level",
38 // FieldKeyMsg: "@message",
39 // },
40 // }
41 FieldMap FieldMap
42}
43
44func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
45 data := make(Fields, len(entry.Data)+3)
46 for k, v := range entry.Data {
47 switch v := v.(type) {
48 case error:
49 // Otherwise errors are ignored by `encoding/json`
50 // https://github.com/sirupsen/logrus/issues/137
51 data[k] = v.Error()
52 default:
53 data[k] = v
54 }
55 }
56 prefixFieldClashes(data)
57
58 timestampFormat := f.TimestampFormat
59 if timestampFormat == "" {
60 timestampFormat = DefaultTimestampFormat
61 }
62
63 if !f.DisableTimestamp {
64 data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
65 }
66 data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
67 data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
68
69 serialized, err := json.Marshal(data)
70 if err != nil {
71 return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
72 }
73 return append(serialized, '\n'), nil
74}