formatter.go raw

   1  package logrus
   2  
   3  import "time"
   4  
   5  // Default key names for the default fields
   6  const (
   7  	defaultTimestampFormat = time.RFC3339
   8  	FieldKeyMsg            = "msg"
   9  	FieldKeyLevel          = "level"
  10  	FieldKeyTime           = "time"
  11  	FieldKeyLogrusError    = "logrus_error"
  12  	FieldKeyFunc           = "func"
  13  	FieldKeyFile           = "file"
  14  )
  15  
  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`.
  26  type Formatter interface {
  27  	Format(*Entry) ([]byte, error)
  28  }
  29  
  30  // This is to not silently overwrite `time`, `msg`, `func` and `level` fields when
  31  // 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.
  42  func 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)
  47  	}
  48  
  49  	msgKey := fieldMap.resolve(FieldKeyMsg)
  50  	if m, ok := data[msgKey]; ok {
  51  		data["fields."+msgKey] = m
  52  		delete(data, msgKey)
  53  	}
  54  
  55  	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  		}
  77  	}
  78  }
  79