11 var bufferPool *sync.Pool
14 bufferPool = &sync.Pool{
15 New: func() interface{} {
16 return new(bytes.Buffer)
21 // Defines the key when adding errors using WithError.
22 var ErrorKey = "error"
24 // An entry is the final or intermediate Logrus logging entry. It contains all
25 // the fields passed with WithField{,s}. It's finally logged when Debug, Info,
26 // Warn, Error, Fatal or Panic is called on it. These objects can be reused and
27 // passed around as much as you wish to avoid field duplication.
31 // Contains all the fields set by the user.
34 // Time at which the log entry was created
37 // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
38 // This field will be set on entry firing and the value will be equal to the one in Logger struct field.
41 // Message passed to Debug, Info, Warn, Error, Fatal or Panic
44 // When formatter is called in entry.log(), an Buffer may be set to entry
48 func NewEntry(logger *Logger) *Entry {
51 // Default is three fields, give a little extra room
52 Data: make(Fields, 5),
56 // Returns the string representation from the reader and ultimately the
58 func (entry *Entry) String() (string, error) {
59 serialized, err := entry.Logger.Formatter.Format(entry)
63 str := string(serialized)
67 // Add an error as single field (using the key defined in ErrorKey) to the Entry.
68 func (entry *Entry) WithError(err error) *Entry {
69 return entry.WithField(ErrorKey, err)
72 // Add a single field to the Entry.
73 func (entry *Entry) WithField(key string, value interface{}) *Entry {
74 return entry.WithFields(Fields{key: value})
77 // Add a map of fields to the Entry.
78 func (entry *Entry) WithFields(fields Fields) *Entry {
79 data := make(Fields, len(entry.Data)+len(fields))
80 for k, v := range entry.Data {
83 for k, v := range fields {
86 return &Entry{Logger: entry.Logger, Data: data}
89 // This function is not declared with a pointer value because otherwise
90 // race conditions will occur when using multiple goroutines
91 func (entry Entry) log(level Level, msg string) {
92 var buffer *bytes.Buffer
93 entry.Time = time.Now()
97 entry.Logger.mu.Lock()
98 err := entry.Logger.Hooks.Fire(level, &entry)
99 entry.Logger.mu.Unlock()
101 entry.Logger.mu.Lock()
102 fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
103 entry.Logger.mu.Unlock()
105 buffer = bufferPool.Get().(*bytes.Buffer)
107 defer bufferPool.Put(buffer)
108 entry.Buffer = buffer
109 serialized, err := entry.Logger.Formatter.Format(&entry)
112 entry.Logger.mu.Lock()
113 fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
114 entry.Logger.mu.Unlock()
116 entry.Logger.mu.Lock()
117 _, err = entry.Logger.Out.Write(serialized)
119 fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
121 entry.Logger.mu.Unlock()
124 // To avoid Entry#log() returning a value that only would make sense for
125 // panic() to use in Entry#Panic(), we avoid the allocation by checking
127 if level <= PanicLevel {
132 func (entry *Entry) Debug(args ...interface{}) {
133 if entry.Logger.level() >= DebugLevel {
134 entry.log(DebugLevel, fmt.Sprint(args...))
138 func (entry *Entry) Print(args ...interface{}) {
142 func (entry *Entry) Info(args ...interface{}) {
143 if entry.Logger.level() >= InfoLevel {
144 entry.log(InfoLevel, fmt.Sprint(args...))
148 func (entry *Entry) Warn(args ...interface{}) {
149 if entry.Logger.level() >= WarnLevel {
150 entry.log(WarnLevel, fmt.Sprint(args...))
154 func (entry *Entry) Warning(args ...interface{}) {
158 func (entry *Entry) Error(args ...interface{}) {
159 if entry.Logger.level() >= ErrorLevel {
160 entry.log(ErrorLevel, fmt.Sprint(args...))
164 func (entry *Entry) Fatal(args ...interface{}) {
165 if entry.Logger.level() >= FatalLevel {
166 entry.log(FatalLevel, fmt.Sprint(args...))
171 func (entry *Entry) Panic(args ...interface{}) {
172 if entry.Logger.level() >= PanicLevel {
173 entry.log(PanicLevel, fmt.Sprint(args...))
175 panic(fmt.Sprint(args...))
178 // Entry Printf family functions
180 func (entry *Entry) Debugf(format string, args ...interface{}) {
181 if entry.Logger.level() >= DebugLevel {
182 entry.Debug(fmt.Sprintf(format, args...))
186 func (entry *Entry) Infof(format string, args ...interface{}) {
187 if entry.Logger.level() >= InfoLevel {
188 entry.Info(fmt.Sprintf(format, args...))
192 func (entry *Entry) Printf(format string, args ...interface{}) {
193 entry.Infof(format, args...)
196 func (entry *Entry) Warnf(format string, args ...interface{}) {
197 if entry.Logger.level() >= WarnLevel {
198 entry.Warn(fmt.Sprintf(format, args...))
202 func (entry *Entry) Warningf(format string, args ...interface{}) {
203 entry.Warnf(format, args...)
206 func (entry *Entry) Errorf(format string, args ...interface{}) {
207 if entry.Logger.level() >= ErrorLevel {
208 entry.Error(fmt.Sprintf(format, args...))
212 func (entry *Entry) Fatalf(format string, args ...interface{}) {
213 if entry.Logger.level() >= FatalLevel {
214 entry.Fatal(fmt.Sprintf(format, args...))
219 func (entry *Entry) Panicf(format string, args ...interface{}) {
220 if entry.Logger.level() >= PanicLevel {
221 entry.Panic(fmt.Sprintf(format, args...))
225 // Entry Println family functions
227 func (entry *Entry) Debugln(args ...interface{}) {
228 if entry.Logger.level() >= DebugLevel {
229 entry.Debug(entry.sprintlnn(args...))
233 func (entry *Entry) Infoln(args ...interface{}) {
234 if entry.Logger.level() >= InfoLevel {
235 entry.Info(entry.sprintlnn(args...))
239 func (entry *Entry) Println(args ...interface{}) {
240 entry.Infoln(args...)
243 func (entry *Entry) Warnln(args ...interface{}) {
244 if entry.Logger.level() >= WarnLevel {
245 entry.Warn(entry.sprintlnn(args...))
249 func (entry *Entry) Warningln(args ...interface{}) {
250 entry.Warnln(args...)
253 func (entry *Entry) Errorln(args ...interface{}) {
254 if entry.Logger.level() >= ErrorLevel {
255 entry.Error(entry.sprintlnn(args...))
259 func (entry *Entry) Fatalln(args ...interface{}) {
260 if entry.Logger.level() >= FatalLevel {
261 entry.Fatal(entry.sprintlnn(args...))
266 func (entry *Entry) Panicln(args ...interface{}) {
267 if entry.Logger.level() >= PanicLevel {
268 entry.Panic(entry.sprintlnn(args...))
272 // Sprintlnn => Sprint no newline. This is to get the behavior of how
273 // fmt.Sprintln where spaces are always added between operands, regardless of
274 // their type. Instead of vendoring the Sprintln implementation to spare a
275 // string allocation, we do the simplest thing.
276 func (entry *Entry) sprintlnn(args ...interface{}) string {
277 msg := fmt.Sprintln(args...)
278 return msg[:len(msg)-1]