1package 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} 309