1 package logrus
2
3 import (
4 "bytes"
5 "fmt"
6 "os"
7 "reflect"
8 "runtime"
9 "strings"
10 "sync"
11 "time"
12 )
13
14 var (
15 bufferPool *sync.Pool
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 bufferPool = &sync.Pool{
34 New: func() interface{} {
35 return new(bytes.Buffer)
36 },
37 }
38
39
40 minimumCallerDepth = 1
41 }
42
43
44 var ErrorKey = "error"
45
46
47
48
49
50 type Entry struct {
51 Logger *Logger
52
53
54 Data Fields
55
56
57 Time time.Time
58
59
60
61 Level Level
62
63
64 Caller *runtime.Frame
65
66
67 Message string
68
69
70 Buffer *bytes.Buffer
71
72
73 err string
74 }
75
76 func NewEntry(logger *Logger) *Entry {
77 return &Entry{
78 Logger: logger,
79
80 Data: make(Fields, 6),
81 }
82 }
83
84
85
86 func (entry *Entry) String() (string, error) {
87 serialized, err := entry.Logger.Formatter.Format(entry)
88 if err != nil {
89 return "", err
90 }
91 str := string(serialized)
92 return str, nil
93 }
94
95
96 func (entry *Entry) WithError(err error) *Entry {
97 return entry.WithField(ErrorKey, err)
98 }
99
100
101 func (entry *Entry) WithField(key string, value interface{}) *Entry {
102 return entry.WithFields(Fields{key: value})
103 }
104
105
106 func (entry *Entry) WithFields(fields Fields) *Entry {
107 data := make(Fields, len(entry.Data)+len(fields))
108 for k, v := range entry.Data {
109 data[k] = v
110 }
111 fieldErr := entry.err
112 for k, v := range fields {
113 isErrField := false
114 if t := reflect.TypeOf(v); t != nil {
115 switch t.Kind() {
116 case reflect.Func:
117 isErrField = true
118 case reflect.Ptr:
119 isErrField = t.Elem().Kind() == reflect.Func
120 }
121 }
122 if isErrField {
123 tmp := fmt.Sprintf("can not add field %q", k)
124 if fieldErr != "" {
125 fieldErr = entry.err + ", " + tmp
126 } else {
127 fieldErr = tmp
128 }
129 } else {
130 data[k] = v
131 }
132 }
133 return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr}
134 }
135
136
137 func (entry *Entry) WithTime(t time.Time) *Entry {
138 return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err}
139 }
140
141
142
143 func getPackageName(f string) string {
144 for {
145 lastPeriod := strings.LastIndex(f, ".")
146 lastSlash := strings.LastIndex(f, "/")
147 if lastPeriod > lastSlash {
148 f = f[:lastPeriod]
149 } else {
150 break
151 }
152 }
153
154 return f
155 }
156
157
158 func getCaller() *runtime.Frame {
159
160 pcs := make([]uintptr, maximumCallerDepth)
161 depth := runtime.Callers(minimumCallerDepth, pcs)
162 frames := runtime.CallersFrames(pcs[:depth])
163
164
165 callerInitOnce.Do(func() {
166 logrusPackage = getPackageName(runtime.FuncForPC(pcs[0]).Name())
167
168
169
170 minimumCallerDepth = knownLogrusFrames
171 })
172
173 for f, again := frames.Next(); again; f, again = frames.Next() {
174 pkg := getPackageName(f.Function)
175
176
177 if pkg != logrusPackage {
178 return &f
179 }
180 }
181
182
183 return nil
184 }
185
186 func (entry Entry) HasCaller() (has bool) {
187 return entry.Logger != nil &&
188 entry.Logger.ReportCaller &&
189 entry.Caller != nil
190 }
191
192
193
194 func (entry Entry) log(level Level, msg string) {
195 var buffer *bytes.Buffer
196
197
198
199
200
201
202 if entry.Time.IsZero() {
203 entry.Time = time.Now()
204 }
205
206 entry.Level = level
207 entry.Message = msg
208 if entry.Logger.ReportCaller {
209 entry.Caller = getCaller()
210 }
211
212 entry.fireHooks()
213
214 buffer = bufferPool.Get().(*bytes.Buffer)
215 buffer.Reset()
216 defer bufferPool.Put(buffer)
217 entry.Buffer = buffer
218
219 entry.write()
220
221 entry.Buffer = nil
222
223
224
225
226 if level <= PanicLevel {
227 panic(&entry)
228 }
229 }
230
231 func (entry *Entry) fireHooks() {
232 entry.Logger.mu.Lock()
233 defer entry.Logger.mu.Unlock()
234 err := entry.Logger.Hooks.Fire(entry.Level, entry)
235 if err != nil {
236 fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
237 }
238 }
239
240 func (entry *Entry) write() {
241 entry.Logger.mu.Lock()
242 defer entry.Logger.mu.Unlock()
243 serialized, err := entry.Logger.Formatter.Format(entry)
244 if err != nil {
245 fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
246 } else {
247 _, err = entry.Logger.Out.Write(serialized)
248 if err != nil {
249 fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
250 }
251 }
252 }
253
254 func (entry *Entry) Log(level Level, args ...interface{}) {
255 if entry.Logger.IsLevelEnabled(level) {
256 entry.log(level, fmt.Sprint(args...))
257 }
258 }
259
260 func (entry *Entry) Trace(args ...interface{}) {
261 entry.Log(TraceLevel, args...)
262 }
263
264 func (entry *Entry) Debug(args ...interface{}) {
265 entry.Log(DebugLevel, args...)
266 }
267
268 func (entry *Entry) Print(args ...interface{}) {
269 entry.Info(args...)
270 }
271
272 func (entry *Entry) Info(args ...interface{}) {
273 entry.Log(InfoLevel, args...)
274 }
275
276 func (entry *Entry) Warn(args ...interface{}) {
277 entry.Log(WarnLevel, args...)
278 }
279
280 func (entry *Entry) Warning(args ...interface{}) {
281 entry.Warn(args...)
282 }
283
284 func (entry *Entry) Error(args ...interface{}) {
285 entry.Log(ErrorLevel, args...)
286 }
287
288 func (entry *Entry) Fatal(args ...interface{}) {
289 entry.Log(FatalLevel, args...)
290 entry.Logger.Exit(1)
291 }
292
293 func (entry *Entry) Panic(args ...interface{}) {
294 entry.Log(PanicLevel, args...)
295 panic(fmt.Sprint(args...))
296 }
297
298
299
300 func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
301 entry.Log(level, fmt.Sprintf(format, args...))
302 }
303
304 func (entry *Entry) Tracef(format string, args ...interface{}) {
305 entry.Logf(TraceLevel, format, args...)
306 }
307
308 func (entry *Entry) Debugf(format string, args ...interface{}) {
309 entry.Logf(DebugLevel, format, args...)
310 }
311
312 func (entry *Entry) Infof(format string, args ...interface{}) {
313 entry.Logf(InfoLevel, format, args...)
314 }
315
316 func (entry *Entry) Printf(format string, args ...interface{}) {
317 entry.Infof(format, args...)
318 }
319
320 func (entry *Entry) Warnf(format string, args ...interface{}) {
321 entry.Logf(WarnLevel, format, args...)
322 }
323
324 func (entry *Entry) Warningf(format string, args ...interface{}) {
325 entry.Warnf(format, args...)
326 }
327
328 func (entry *Entry) Errorf(format string, args ...interface{}) {
329 entry.Logf(ErrorLevel, format, args...)
330 }
331
332 func (entry *Entry) Fatalf(format string, args ...interface{}) {
333 entry.Logf(FatalLevel, format, args...)
334 entry.Logger.Exit(1)
335 }
336
337 func (entry *Entry) Panicf(format string, args ...interface{}) {
338 entry.Logf(PanicLevel, format, args...)
339 }
340
341
342
343 func (entry *Entry) Logln(level Level, args ...interface{}) {
344 if entry.Logger.IsLevelEnabled(level) {
345 entry.Log(level, entry.sprintlnn(args...))
346 }
347 }
348
349 func (entry *Entry) Traceln(args ...interface{}) {
350 entry.Logln(TraceLevel, args...)
351 }
352
353 func (entry *Entry) Debugln(args ...interface{}) {
354 entry.Logln(DebugLevel, args...)
355 }
356
357 func (entry *Entry) Infoln(args ...interface{}) {
358 entry.Logln(InfoLevel, args...)
359 }
360
361 func (entry *Entry) Println(args ...interface{}) {
362 entry.Infoln(args...)
363 }
364
365 func (entry *Entry) Warnln(args ...interface{}) {
366 entry.Logln(WarnLevel, args...)
367 }
368
369 func (entry *Entry) Warningln(args ...interface{}) {
370 entry.Warnln(args...)
371 }
372
373 func (entry *Entry) Errorln(args ...interface{}) {
374 entry.Logln(ErrorLevel, args...)
375 }
376
377 func (entry *Entry) Fatalln(args ...interface{}) {
378 entry.Logln(FatalLevel, args...)
379 entry.Logger.Exit(1)
380 }
381
382 func (entry *Entry) Panicln(args ...interface{}) {
383 entry.Logln(PanicLevel, args...)
384 }
385
386
387
388
389
390 func (entry *Entry) sprintlnn(args ...interface{}) string {
391 msg := fmt.Sprintln(args...)
392 return msg[:len(msg)-1]
393 }
394
View as plain text