aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/sirupsen/logrus/entry.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/sirupsen/logrus/entry.go')
-rw-r--r--vendor/github.com/sirupsen/logrus/entry.go442
1 files changed, 442 insertions, 0 deletions
diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go
new file mode 100644
index 0000000..71cdbbc
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/entry.go
@@ -0,0 +1,442 @@
1package logrus
2
3import (
4 "bytes"
5 "context"
6 "fmt"
7 "os"
8 "reflect"
9 "runtime"
10 "strings"
11 "sync"
12 "time"
13)
14
15var (
16
17 // qualified package name, cached at first use
18 logrusPackage string
19
20 // Positions in the call stack when tracing to report the calling method
21 minimumCallerDepth int
22
23 // Used for caller information initialisation
24 callerInitOnce sync.Once
25)
26
27const (
28 maximumCallerDepth int = 25
29 knownLogrusFrames int = 4
30)
31
32func init() {
33 // start at the bottom of the stack before the package-name cache is primed
34 minimumCallerDepth = 1
35}
36
37// Defines the key when adding errors using WithError.
38var ErrorKey = "error"
39
40// An entry is the final or intermediate Logrus logging entry. It contains all
41// the fields passed with WithField{,s}. It's finally logged when Trace, Debug,
42// Info, Warn, Error, Fatal or Panic is called on it. These objects can be
43// reused and passed around as much as you wish to avoid field duplication.
44type Entry struct {
45 Logger *Logger
46
47 // Contains all the fields set by the user.
48 Data Fields
49
50 // Time at which the log entry was created
51 Time time.Time
52
53 // Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic
54 // This field will be set on entry firing and the value will be equal to the one in Logger struct field.
55 Level Level
56
57 // Calling method, with package name
58 Caller *runtime.Frame
59
60 // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
61 Message string
62
63 // When formatter is called in entry.log(), a Buffer may be set to entry
64 Buffer *bytes.Buffer
65
66 // Contains the context set by the user. Useful for hook processing etc.
67 Context context.Context
68
69 // err may contain a field formatting error
70 err string
71}
72
73func NewEntry(logger *Logger) *Entry {
74 return &Entry{
75 Logger: logger,
76 // Default is three fields, plus one optional. Give a little extra room.
77 Data: make(Fields, 6),
78 }
79}
80
81func (entry *Entry) Dup() *Entry {
82 data := make(Fields, len(entry.Data))
83 for k, v := range entry.Data {
84 data[k] = v
85 }
86 return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, Context: entry.Context, err: entry.err}
87}
88
89// Returns the bytes representation of this entry from the formatter.
90func (entry *Entry) Bytes() ([]byte, error) {
91 return entry.Logger.Formatter.Format(entry)
92}
93
94// Returns the string representation from the reader and ultimately the
95// formatter.
96func (entry *Entry) String() (string, error) {
97 serialized, err := entry.Bytes()
98 if err != nil {
99 return "", err
100 }
101 str := string(serialized)
102 return str, nil
103}
104
105// Add an error as single field (using the key defined in ErrorKey) to the Entry.
106func (entry *Entry) WithError(err error) *Entry {
107 return entry.WithField(ErrorKey, err)
108}
109
110// Add a context to the Entry.
111func (entry *Entry) WithContext(ctx context.Context) *Entry {
112 dataCopy := make(Fields, len(entry.Data))
113 for k, v := range entry.Data {
114 dataCopy[k] = v
115 }
116 return &Entry{Logger: entry.Logger, Data: dataCopy, Time: entry.Time, err: entry.err, Context: ctx}
117}
118
119// Add a single field to the Entry.
120func (entry *Entry) WithField(key string, value interface{}) *Entry {
121 return entry.WithFields(Fields{key: value})
122}
123
124// Add a map of fields to the Entry.
125func (entry *Entry) WithFields(fields Fields) *Entry {
126 data := make(Fields, len(entry.Data)+len(fields))
127 for k, v := range entry.Data {
128 data[k] = v
129 }
130 fieldErr := entry.err
131 for k, v := range fields {
132 isErrField := false
133 if t := reflect.TypeOf(v); t != nil {
134 switch {
135 case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func:
136 isErrField = true
137 }
138 }
139 if isErrField {
140 tmp := fmt.Sprintf("can not add field %q", k)
141 if fieldErr != "" {
142 fieldErr = entry.err + ", " + tmp
143 } else {
144 fieldErr = tmp
145 }
146 } else {
147 data[k] = v
148 }
149 }
150 return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context}
151}
152
153// Overrides the time of the Entry.
154func (entry *Entry) WithTime(t time.Time) *Entry {
155 dataCopy := make(Fields, len(entry.Data))
156 for k, v := range entry.Data {
157 dataCopy[k] = v
158 }
159 return &Entry{Logger: entry.Logger, Data: dataCopy, Time: t, err: entry.err, Context: entry.Context}
160}
161
162// getPackageName reduces a fully qualified function name to the package name
163// There really ought to be to be a better way...
164func getPackageName(f string) string {
165 for {
166 lastPeriod := strings.LastIndex(f, ".")
167 lastSlash := strings.LastIndex(f, "/")
168 if lastPeriod > lastSlash {
169 f = f[:lastPeriod]
170 } else {
171 break
172 }
173 }
174
175 return f
176}
177
178// getCaller retrieves the name of the first non-logrus calling function
179func getCaller() *runtime.Frame {
180 // cache this package's fully-qualified name
181 callerInitOnce.Do(func() {
182 pcs := make([]uintptr, maximumCallerDepth)
183 _ = runtime.Callers(0, pcs)
184
185 // dynamic get the package name and the minimum caller depth
186 for i := 0; i < maximumCallerDepth; i++ {
187 funcName := runtime.FuncForPC(pcs[i]).Name()
188 if strings.Contains(funcName, "getCaller") {
189 logrusPackage = getPackageName(funcName)
190 break
191 }
192 }
193
194 minimumCallerDepth = knownLogrusFrames
195 })
196
197 // Restrict the lookback frames to avoid runaway lookups
198 pcs := make([]uintptr, maximumCallerDepth)
199 depth := runtime.Callers(minimumCallerDepth, pcs)
200 frames := runtime.CallersFrames(pcs[:depth])
201
202 for f, again := frames.Next(); again; f, again = frames.Next() {
203 pkg := getPackageName(f.Function)
204
205 // If the caller isn't part of this package, we're done
206 if pkg != logrusPackage {
207 return &f //nolint:scopelint
208 }
209 }
210
211 // if we got here, we failed to find the caller's context
212 return nil
213}
214
215func (entry Entry) HasCaller() (has bool) {
216 return entry.Logger != nil &&
217 entry.Logger.ReportCaller &&
218 entry.Caller != nil
219}
220
221func (entry *Entry) log(level Level, msg string) {
222 var buffer *bytes.Buffer
223
224 newEntry := entry.Dup()
225
226 if newEntry.Time.IsZero() {
227 newEntry.Time = time.Now()
228 }
229
230 newEntry.Level = level
231 newEntry.Message = msg
232
233 newEntry.Logger.mu.Lock()
234 reportCaller := newEntry.Logger.ReportCaller
235 bufPool := newEntry.getBufferPool()
236 newEntry.Logger.mu.Unlock()
237
238 if reportCaller {
239 newEntry.Caller = getCaller()
240 }
241
242 newEntry.fireHooks()
243 buffer = bufPool.Get()
244 defer func() {
245 newEntry.Buffer = nil
246 buffer.Reset()
247 bufPool.Put(buffer)
248 }()
249 buffer.Reset()
250 newEntry.Buffer = buffer
251
252 newEntry.write()
253
254 newEntry.Buffer = nil
255
256 // To avoid Entry#log() returning a value that only would make sense for
257 // panic() to use in Entry#Panic(), we avoid the allocation by checking
258 // directly here.
259 if level <= PanicLevel {
260 panic(newEntry)
261 }
262}
263
264func (entry *Entry) getBufferPool() (pool BufferPool) {
265 if entry.Logger.BufferPool != nil {
266 return entry.Logger.BufferPool
267 }
268 return bufferPool
269}
270
271func (entry *Entry) fireHooks() {
272 var tmpHooks LevelHooks
273 entry.Logger.mu.Lock()
274 tmpHooks = make(LevelHooks, len(entry.Logger.Hooks))
275 for k, v := range entry.Logger.Hooks {
276 tmpHooks[k] = v
277 }
278 entry.Logger.mu.Unlock()
279
280 err := tmpHooks.Fire(entry.Level, entry)
281 if err != nil {
282 fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
283 }
284}
285
286func (entry *Entry) write() {
287 entry.Logger.mu.Lock()
288 defer entry.Logger.mu.Unlock()
289 serialized, err := entry.Logger.Formatter.Format(entry)
290 if err != nil {
291 fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
292 return
293 }
294 if _, err := entry.Logger.Out.Write(serialized); err != nil {
295 fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
296 }
297}
298
299// Log will log a message at the level given as parameter.
300// Warning: using Log at Panic or Fatal level will not respectively Panic nor Exit.
301// For this behaviour Entry.Panic or Entry.Fatal should be used instead.
302func (entry *Entry) Log(level Level, args ...interface{}) {
303 if entry.Logger.IsLevelEnabled(level) {
304 entry.log(level, fmt.Sprint(args...))
305 }
306}
307
308func (entry *Entry) Trace(args ...interface{}) {
309 entry.Log(TraceLevel, args...)
310}
311
312func (entry *Entry) Debug(args ...interface{}) {
313 entry.Log(DebugLevel, args...)
314}
315
316func (entry *Entry) Print(args ...interface{}) {
317 entry.Info(args...)
318}
319
320func (entry *Entry) Info(args ...interface{}) {
321 entry.Log(InfoLevel, args...)
322}
323
324func (entry *Entry) Warn(args ...interface{}) {
325 entry.Log(WarnLevel, args...)
326}
327
328func (entry *Entry) Warning(args ...interface{}) {
329 entry.Warn(args...)
330}
331
332func (entry *Entry) Error(args ...interface{}) {
333 entry.Log(ErrorLevel, args...)
334}
335
336func (entry *Entry) Fatal(args ...interface{}) {
337 entry.Log(FatalLevel, args...)
338 entry.Logger.Exit(1)
339}
340
341func (entry *Entry) Panic(args ...interface{}) {
342 entry.Log(PanicLevel, args...)
343}
344
345// Entry Printf family functions
346
347func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
348 if entry.Logger.IsLevelEnabled(level) {
349 entry.Log(level, fmt.Sprintf(format, args...))
350 }
351}
352
353func (entry *Entry) Tracef(format string, args ...interface{}) {
354 entry.Logf(TraceLevel, format, args...)
355}
356
357func (entry *Entry) Debugf(format string, args ...interface{}) {
358 entry.Logf(DebugLevel, format, args...)
359}
360
361func (entry *Entry) Infof(format string, args ...interface{}) {
362 entry.Logf(InfoLevel, format, args...)
363}
364
365func (entry *Entry) Printf(format string, args ...interface{}) {
366 entry.Infof(format, args...)
367}
368
369func (entry *Entry) Warnf(format string, args ...interface{}) {
370 entry.Logf(WarnLevel, format, args...)
371}
372
373func (entry *Entry) Warningf(format string, args ...interface{}) {
374 entry.Warnf(format, args...)
375}
376
377func (entry *Entry) Errorf(format string, args ...interface{}) {
378 entry.Logf(ErrorLevel, format, args...)
379}
380
381func (entry *Entry) Fatalf(format string, args ...interface{}) {
382 entry.Logf(FatalLevel, format, args...)
383 entry.Logger.Exit(1)
384}
385
386func (entry *Entry) Panicf(format string, args ...interface{}) {
387 entry.Logf(PanicLevel, format, args...)
388}
389
390// Entry Println family functions
391
392func (entry *Entry) Logln(level Level, args ...interface{}) {
393 if entry.Logger.IsLevelEnabled(level) {
394 entry.Log(level, entry.sprintlnn(args...))
395 }
396}
397
398func (entry *Entry) Traceln(args ...interface{}) {
399 entry.Logln(TraceLevel, args...)
400}
401
402func (entry *Entry) Debugln(args ...interface{}) {
403 entry.Logln(DebugLevel, args...)
404}
405
406func (entry *Entry) Infoln(args ...interface{}) {
407 entry.Logln(InfoLevel, args...)
408}
409
410func (entry *Entry) Println(args ...interface{}) {
411 entry.Infoln(args...)
412}
413
414func (entry *Entry) Warnln(args ...interface{}) {
415 entry.Logln(WarnLevel, args...)
416}
417
418func (entry *Entry) Warningln(args ...interface{}) {
419 entry.Warnln(args...)
420}
421
422func (entry *Entry) Errorln(args ...interface{}) {
423 entry.Logln(ErrorLevel, args...)
424}
425
426func (entry *Entry) Fatalln(args ...interface{}) {
427 entry.Logln(FatalLevel, args...)
428 entry.Logger.Exit(1)
429}
430
431func (entry *Entry) Panicln(args ...interface{}) {
432 entry.Logln(PanicLevel, args...)
433}
434
435// Sprintlnn => Sprint no newline. This is to get the behavior of how
436// fmt.Sprintln where spaces are always added between operands, regardless of
437// their type. Instead of vendoring the Sprintln implementation to spare a
438// string allocation, we do the simplest thing.
439func (entry *Entry) sprintlnn(args ...interface{}) string {
440 msg := fmt.Sprintln(args...)
441 return msg[:len(msg)-1]
442}