blob: 408883773ebbd70f8f5128ed74747039ec8ee0f1 [file] [log] [blame]
Jonathan Hartf86817b2018-08-17 10:35:54 -07001package logrus
2
3import "time"
4
Matteo Scandolo1f49bf52018-11-20 13:56:45 -08005// Default key names for the default fields
6const (
7 defaultTimestampFormat = time.RFC3339
8 FieldKeyMsg = "msg"
9 FieldKeyLevel = "level"
10 FieldKeyTime = "time"
11 FieldKeyLogrusError = "logrus_error"
12 FieldKeyFunc = "func"
13 FieldKeyFile = "file"
14)
Jonathan Hartf86817b2018-08-17 10:35:54 -070015
16// The Formatter interface is used to implement a custom Formatter. It takes an
17// `Entry`. It exposes all the fields, including the default ones:
18//
19// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
20// * `entry.Data["time"]`. The timestamp.
21// * `entry.Data["level"]. The level the entry was logged at.
22//
23// Any additional fields added with `WithField` or `WithFields` are also in
24// `entry.Data`. Format is expected to return an array of bytes which are then
25// logged to `logger.Out`.
26type Formatter interface {
27 Format(*Entry) ([]byte, error)
28}
29
Matteo Scandolo1f49bf52018-11-20 13:56:45 -080030// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when
Jonathan Hartf86817b2018-08-17 10:35:54 -070031// dumping it. If this code wasn't there doing:
32//
33// logrus.WithField("level", 1).Info("hello")
34//
35// Would just silently drop the user provided level. Instead with this code
36// it'll logged as:
37//
38// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
39//
40// It's not exported because it's still using Data in an opinionated way. It's to
41// avoid code duplication between the two default formatters.
Matteo Scandolo1f49bf52018-11-20 13:56:45 -080042func prefixFieldClashes(data Fields, fieldMap FieldMap, reportCaller bool) {
43 timeKey := fieldMap.resolve(FieldKeyTime)
44 if t, ok := data[timeKey]; ok {
45 data["fields."+timeKey] = t
46 delete(data, timeKey)
Jonathan Hartf86817b2018-08-17 10:35:54 -070047 }
48
Matteo Scandolo1f49bf52018-11-20 13:56:45 -080049 msgKey := fieldMap.resolve(FieldKeyMsg)
50 if m, ok := data[msgKey]; ok {
51 data["fields."+msgKey] = m
52 delete(data, msgKey)
Jonathan Hartf86817b2018-08-17 10:35:54 -070053 }
54
Matteo Scandolo1f49bf52018-11-20 13:56:45 -080055 levelKey := fieldMap.resolve(FieldKeyLevel)
56 if l, ok := data[levelKey]; ok {
57 data["fields."+levelKey] = l
58 delete(data, levelKey)
59 }
60
61 logrusErrKey := fieldMap.resolve(FieldKeyLogrusError)
62 if l, ok := data[logrusErrKey]; ok {
63 data["fields."+logrusErrKey] = l
64 delete(data, logrusErrKey)
65 }
66
67 // If reportCaller is not set, 'func' will not conflict.
68 if reportCaller {
69 funcKey := fieldMap.resolve(FieldKeyFunc)
70 if l, ok := data[funcKey]; ok {
71 data["fields."+funcKey] = l
72 }
73 fileKey := fieldMap.resolve(FieldKeyFile)
74 if l, ok := data[fileKey]; ok {
75 data["fields."+fileKey] = l
76 }
Jonathan Hartf86817b2018-08-17 10:35:54 -070077 }
78}