blob: b769f3d3522c1baa000a02b0c9763b8356f23e75 [file] [log] [blame]
David K. Bainbridge528b3182017-01-23 08:51:59 -08001package logrus
2
3import (
4 "io"
5 "os"
6 "sync"
7)
8
9type Logger struct {
10 // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
11 // file, or leave it default which is `os.Stderr`. You can also set this to
12 // something more adventorous, such as logging to Kafka.
13 Out io.Writer
14 // Hooks for the logger instance. These allow firing events based on logging
15 // levels and log entries. For example, to send errors to an error tracking
16 // service, log to StatsD or dump the core on fatal errors.
17 Hooks LevelHooks
18 // All log entries pass through the formatter before logged to Out. The
19 // included formatters are `TextFormatter` and `JSONFormatter` for which
20 // TextFormatter is the default. In development (when a TTY is attached) it
21 // logs with colors, but to a file it wouldn't. You can easily implement your
22 // own that implements the `Formatter` interface, see the `README` or included
23 // formatters for examples.
24 Formatter Formatter
25 // The logging level the logger should log at. This is typically (and defaults
26 // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
27 // logged. `logrus.Debug` is useful in
28 Level Level
29 // Used to sync writing to the log. Locking is enabled by Default
30 mu MutexWrap
31 // Reusable empty entry
32 entryPool sync.Pool
33}
34
35type MutexWrap struct {
36 lock sync.Mutex
37 disabled bool
38}
39
40func (mw *MutexWrap) Lock() {
41 if !mw.disabled {
42 mw.lock.Lock()
43 }
44}
45
46func (mw *MutexWrap) Unlock() {
47 if !mw.disabled {
48 mw.lock.Unlock()
49 }
50}
51
52func (mw *MutexWrap) Disable() {
53 mw.disabled = true
54}
55
56// Creates a new logger. Configuration should be set by changing `Formatter`,
57// `Out` and `Hooks` directly on the default logger instance. You can also just
58// instantiate your own:
59//
60// var log = &Logger{
61// Out: os.Stderr,
62// Formatter: new(JSONFormatter),
63// Hooks: make(LevelHooks),
64// Level: logrus.DebugLevel,
65// }
66//
67// It's recommended to make this a global instance called `log`.
68func New() *Logger {
69 return &Logger{
70 Out: os.Stderr,
71 Formatter: new(TextFormatter),
72 Hooks: make(LevelHooks),
73 Level: InfoLevel,
74 }
75}
76
77func (logger *Logger) newEntry() *Entry {
78 entry, ok := logger.entryPool.Get().(*Entry)
79 if ok {
80 return entry
81 }
82 return NewEntry(logger)
83}
84
85func (logger *Logger) releaseEntry(entry *Entry) {
86 logger.entryPool.Put(entry)
87}
88
89// Adds a field to the log entry, note that it doesn't log until you call
90// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
91// If you want multiple fields, use `WithFields`.
92func (logger *Logger) WithField(key string, value interface{}) *Entry {
93 entry := logger.newEntry()
94 defer logger.releaseEntry(entry)
95 return entry.WithField(key, value)
96}
97
98// Adds a struct of fields to the log entry. All it does is call `WithField` for
99// each `Field`.
100func (logger *Logger) WithFields(fields Fields) *Entry {
101 entry := logger.newEntry()
102 defer logger.releaseEntry(entry)
103 return entry.WithFields(fields)
104}
105
106// Add an error as single field to the log entry. All it does is call
107// `WithError` for the given `error`.
108func (logger *Logger) WithError(err error) *Entry {
109 entry := logger.newEntry()
110 defer logger.releaseEntry(entry)
111 return entry.WithError(err)
112}
113
114func (logger *Logger) Debugf(format string, args ...interface{}) {
115 if logger.Level >= DebugLevel {
116 entry := logger.newEntry()
117 entry.Debugf(format, args...)
118 logger.releaseEntry(entry)
119 }
120}
121
122func (logger *Logger) Infof(format string, args ...interface{}) {
123 if logger.Level >= InfoLevel {
124 entry := logger.newEntry()
125 entry.Infof(format, args...)
126 logger.releaseEntry(entry)
127 }
128}
129
130func (logger *Logger) Printf(format string, args ...interface{}) {
131 entry := logger.newEntry()
132 entry.Printf(format, args...)
133 logger.releaseEntry(entry)
134}
135
136func (logger *Logger) Warnf(format string, args ...interface{}) {
137 if logger.Level >= WarnLevel {
138 entry := logger.newEntry()
139 entry.Warnf(format, args...)
140 logger.releaseEntry(entry)
141 }
142}
143
144func (logger *Logger) Warningf(format string, args ...interface{}) {
145 if logger.Level >= WarnLevel {
146 entry := logger.newEntry()
147 entry.Warnf(format, args...)
148 logger.releaseEntry(entry)
149 }
150}
151
152func (logger *Logger) Errorf(format string, args ...interface{}) {
153 if logger.Level >= ErrorLevel {
154 entry := logger.newEntry()
155 entry.Errorf(format, args...)
156 logger.releaseEntry(entry)
157 }
158}
159
160func (logger *Logger) Fatalf(format string, args ...interface{}) {
161 if logger.Level >= FatalLevel {
162 entry := logger.newEntry()
163 entry.Fatalf(format, args...)
164 logger.releaseEntry(entry)
165 }
166 Exit(1)
167}
168
169func (logger *Logger) Panicf(format string, args ...interface{}) {
170 if logger.Level >= PanicLevel {
171 entry := logger.newEntry()
172 entry.Panicf(format, args...)
173 logger.releaseEntry(entry)
174 }
175}
176
177func (logger *Logger) Debug(args ...interface{}) {
178 if logger.Level >= DebugLevel {
179 entry := logger.newEntry()
180 entry.Debug(args...)
181 logger.releaseEntry(entry)
182 }
183}
184
185func (logger *Logger) Info(args ...interface{}) {
186 if logger.Level >= InfoLevel {
187 entry := logger.newEntry()
188 entry.Info(args...)
189 logger.releaseEntry(entry)
190 }
191}
192
193func (logger *Logger) Print(args ...interface{}) {
194 entry := logger.newEntry()
195 entry.Info(args...)
196 logger.releaseEntry(entry)
197}
198
199func (logger *Logger) Warn(args ...interface{}) {
200 if logger.Level >= WarnLevel {
201 entry := logger.newEntry()
202 entry.Warn(args...)
203 logger.releaseEntry(entry)
204 }
205}
206
207func (logger *Logger) Warning(args ...interface{}) {
208 if logger.Level >= WarnLevel {
209 entry := logger.newEntry()
210 entry.Warn(args...)
211 logger.releaseEntry(entry)
212 }
213}
214
215func (logger *Logger) Error(args ...interface{}) {
216 if logger.Level >= ErrorLevel {
217 entry := logger.newEntry()
218 entry.Error(args...)
219 logger.releaseEntry(entry)
220 }
221}
222
223func (logger *Logger) Fatal(args ...interface{}) {
224 if logger.Level >= FatalLevel {
225 entry := logger.newEntry()
226 entry.Fatal(args...)
227 logger.releaseEntry(entry)
228 }
229 Exit(1)
230}
231
232func (logger *Logger) Panic(args ...interface{}) {
233 if logger.Level >= PanicLevel {
234 entry := logger.newEntry()
235 entry.Panic(args...)
236 logger.releaseEntry(entry)
237 }
238}
239
240func (logger *Logger) Debugln(args ...interface{}) {
241 if logger.Level >= DebugLevel {
242 entry := logger.newEntry()
243 entry.Debugln(args...)
244 logger.releaseEntry(entry)
245 }
246}
247
248func (logger *Logger) Infoln(args ...interface{}) {
249 if logger.Level >= InfoLevel {
250 entry := logger.newEntry()
251 entry.Infoln(args...)
252 logger.releaseEntry(entry)
253 }
254}
255
256func (logger *Logger) Println(args ...interface{}) {
257 entry := logger.newEntry()
258 entry.Println(args...)
259 logger.releaseEntry(entry)
260}
261
262func (logger *Logger) Warnln(args ...interface{}) {
263 if logger.Level >= WarnLevel {
264 entry := logger.newEntry()
265 entry.Warnln(args...)
266 logger.releaseEntry(entry)
267 }
268}
269
270func (logger *Logger) Warningln(args ...interface{}) {
271 if logger.Level >= WarnLevel {
272 entry := logger.newEntry()
273 entry.Warnln(args...)
274 logger.releaseEntry(entry)
275 }
276}
277
278func (logger *Logger) Errorln(args ...interface{}) {
279 if logger.Level >= ErrorLevel {
280 entry := logger.newEntry()
281 entry.Errorln(args...)
282 logger.releaseEntry(entry)
283 }
284}
285
286func (logger *Logger) Fatalln(args ...interface{}) {
287 if logger.Level >= FatalLevel {
288 entry := logger.newEntry()
289 entry.Fatalln(args...)
290 logger.releaseEntry(entry)
291 }
292 Exit(1)
293}
294
295func (logger *Logger) Panicln(args ...interface{}) {
296 if logger.Level >= PanicLevel {
297 entry := logger.newEntry()
298 entry.Panicln(args...)
299 logger.releaseEntry(entry)
300 }
301}
302
303//When file is opened with appending mode, it's safe to
304//write concurrently to a file (within 4k message on Linux).
305//In these cases user can choose to disable the lock.
306func (logger *Logger) SetNoLock() {
307 logger.mu.Disable()
308}