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