1 package logrus
2
3 import (
4 "bytes"
5 "context"
6 "fmt"
7 "os"
8 "reflect"
9 "runtime"
10 "strings"
11 "sync"
12 "time"
13 )
14
15 var (
16
17
18 logrusPackage string
19
20
21 minimumCallerDepth int
22
23
24 callerInitOnce sync.Once
25 )
26
27 const (
28 maximumCallerDepth int = 25
29 knownLogrusFrames int = 4
30 )
31
32 func init() {
33
34 minimumCallerDepth = 1
35 }
36
37
38 var ErrorKey = "error"
39
40
41
42
43
44 type Entry struct {
45 Logger *Logger
46
47
48 Data Fields
49
50
51 Time time.Time
52
53
54
55 Level Level
56
57
58 Caller *runtime.Frame
59
60
61 Message string
62
63
64 Buffer *bytes.Buffer
65
66
67 Context context.Context
68
69
70 err string
71 }
72
73 func NewEntry(logger *Logger) *Entry {
74 return &Entry{
75 Logger: logger,
76
77 Data: make(Fields, 6),
78 }
79 }
80
81 func (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
90 func (entry *Entry) Bytes() ([]byte, error) {
91 return entry.Logger.Formatter.Format(entry)
92 }
93
94
95
96 func (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
106 func (entry *Entry) WithError(err error) *Entry {
107 return entry.WithField(ErrorKey, err)
108 }
109
110
111 func (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
120 func (entry *Entry) WithField(key string, value interface{}) *Entry {
121 return entry.WithFields(Fields{key: value})
122 }
123
124
125 func (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
154 func (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
163
164 func 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
179 func getCaller() *runtime.Frame {
180
181 callerInitOnce.Do(func() {
182 pcs := make([]uintptr, maximumCallerDepth)
183 _ = runtime.Callers(0, pcs)
184
185
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
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
206 if pkg != logrusPackage {
207 return &f
208 }
209 }
210
211
212 return nil
213 }
214
215 func (entry Entry) HasCaller() (has bool) {
216 return entry.Logger != nil &&
217 entry.Logger.ReportCaller &&
218 entry.Caller != nil
219 }
220
221 func (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
257
258
259 if level <= PanicLevel {
260 panic(newEntry)
261 }
262 }
263
264 func (entry *Entry) getBufferPool() (pool BufferPool) {
265 if entry.Logger.BufferPool != nil {
266 return entry.Logger.BufferPool
267 }
268 return bufferPool
269 }
270
271 func (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
286 func (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
300
301
302 func (entry *Entry) Log(level Level, args ...interface{}) {
303 if entry.Logger.IsLevelEnabled(level) {
304 entry.log(level, fmt.Sprint(args...))
305 }
306 }
307
308 func (entry *Entry) Trace(args ...interface{}) {
309 entry.Log(TraceLevel, args...)
310 }
311
312 func (entry *Entry) Debug(args ...interface{}) {
313 entry.Log(DebugLevel, args...)
314 }
315
316 func (entry *Entry) Print(args ...interface{}) {
317 entry.Info(args...)
318 }
319
320 func (entry *Entry) Info(args ...interface{}) {
321 entry.Log(InfoLevel, args...)
322 }
323
324 func (entry *Entry) Warn(args ...interface{}) {
325 entry.Log(WarnLevel, args...)
326 }
327
328 func (entry *Entry) Warning(args ...interface{}) {
329 entry.Warn(args...)
330 }
331
332 func (entry *Entry) Error(args ...interface{}) {
333 entry.Log(ErrorLevel, args...)
334 }
335
336 func (entry *Entry) Fatal(args ...interface{}) {
337 entry.Log(FatalLevel, args...)
338 entry.Logger.Exit(1)
339 }
340
341 func (entry *Entry) Panic(args ...interface{}) {
342 entry.Log(PanicLevel, args...)
343 }
344
345
346
347 func (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
353 func (entry *Entry) Tracef(format string, args ...interface{}) {
354 entry.Logf(TraceLevel, format, args...)
355 }
356
357 func (entry *Entry) Debugf(format string, args ...interface{}) {
358 entry.Logf(DebugLevel, format, args...)
359 }
360
361 func (entry *Entry) Infof(format string, args ...interface{}) {
362 entry.Logf(InfoLevel, format, args...)
363 }
364
365 func (entry *Entry) Printf(format string, args ...interface{}) {
366 entry.Infof(format, args...)
367 }
368
369 func (entry *Entry) Warnf(format string, args ...interface{}) {
370 entry.Logf(WarnLevel, format, args...)
371 }
372
373 func (entry *Entry) Warningf(format string, args ...interface{}) {
374 entry.Warnf(format, args...)
375 }
376
377 func (entry *Entry) Errorf(format string, args ...interface{}) {
378 entry.Logf(ErrorLevel, format, args...)
379 }
380
381 func (entry *Entry) Fatalf(format string, args ...interface{}) {
382 entry.Logf(FatalLevel, format, args...)
383 entry.Logger.Exit(1)
384 }
385
386 func (entry *Entry) Panicf(format string, args ...interface{}) {
387 entry.Logf(PanicLevel, format, args...)
388 }
389
390
391
392 func (entry *Entry) Logln(level Level, args ...interface{}) {
393 if entry.Logger.IsLevelEnabled(level) {
394 entry.Log(level, entry.sprintlnn(args...))
395 }
396 }
397
398 func (entry *Entry) Traceln(args ...interface{}) {
399 entry.Logln(TraceLevel, args...)
400 }
401
402 func (entry *Entry) Debugln(args ...interface{}) {
403 entry.Logln(DebugLevel, args...)
404 }
405
406 func (entry *Entry) Infoln(args ...interface{}) {
407 entry.Logln(InfoLevel, args...)
408 }
409
410 func (entry *Entry) Println(args ...interface{}) {
411 entry.Infoln(args...)
412 }
413
414 func (entry *Entry) Warnln(args ...interface{}) {
415 entry.Logln(WarnLevel, args...)
416 }
417
418 func (entry *Entry) Warningln(args ...interface{}) {
419 entry.Warnln(args...)
420 }
421
422 func (entry *Entry) Errorln(args ...interface{}) {
423 entry.Logln(ErrorLevel, args...)
424 }
425
426 func (entry *Entry) Fatalln(args ...interface{}) {
427 entry.Logln(FatalLevel, args...)
428 entry.Logger.Exit(1)
429 }
430
431 func (entry *Entry) Panicln(args ...interface{}) {
432 entry.Logln(PanicLevel, args...)
433 }
434
435
436
437
438
439 func (entry *Entry) sprintlnn(args ...interface{}) string {
440 msg := fmt.Sprintln(args...)
441 return msg[:len(msg)-1]
442 }
443
View as plain text