logger.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. package logrus
  2. import (
  3. "io"
  4. "os"
  5. "sync"
  6. "sync/atomic"
  7. "time"
  8. )
  9. type 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.
  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. type MutexWrap struct {
  35. lock sync.Mutex
  36. disabled bool
  37. }
  38. func (mw *MutexWrap) Lock() {
  39. if !mw.disabled {
  40. mw.lock.Lock()
  41. }
  42. }
  43. func (mw *MutexWrap) Unlock() {
  44. if !mw.disabled {
  45. mw.lock.Unlock()
  46. }
  47. }
  48. func (mw *MutexWrap) Disable() {
  49. mw.disabled = true
  50. }
  51. // Creates a new logger. Configuration should be set by changing `Formatter`,
  52. // `Out` and `Hooks` directly on the default logger instance. You can also just
  53. // instantiate your own:
  54. //
  55. // var log = &Logger{
  56. // Out: os.Stderr,
  57. // Formatter: new(JSONFormatter),
  58. // Hooks: make(LevelHooks),
  59. // Level: logrus.DebugLevel,
  60. // }
  61. //
  62. // It's recommended to make this a global instance called `log`.
  63. func New() *Logger {
  64. return &Logger{
  65. Out: os.Stderr,
  66. Formatter: new(TextFormatter),
  67. Hooks: make(LevelHooks),
  68. Level: InfoLevel,
  69. }
  70. }
  71. func (logger *Logger) newEntry() *Entry {
  72. entry, ok := logger.entryPool.Get().(*Entry)
  73. if ok {
  74. return entry
  75. }
  76. return NewEntry(logger)
  77. }
  78. func (logger *Logger) releaseEntry(entry *Entry) {
  79. entry.Data = map[string]interface{}{}
  80. logger.entryPool.Put(entry)
  81. }
  82. // Adds a field to the log entry, note that it doesn't log until you call
  83. // Debug, Print, Info, Warn, Error, Fatal or Panic. It only creates a log entry.
  84. // If you want multiple fields, use `WithFields`.
  85. func (logger *Logger) WithField(key string, value interface{}) *Entry {
  86. entry := logger.newEntry()
  87. defer logger.releaseEntry(entry)
  88. return entry.WithField(key, value)
  89. }
  90. // Adds a struct of fields to the log entry. All it does is call `WithField` for
  91. // each `Field`.
  92. func (logger *Logger) WithFields(fields Fields) *Entry {
  93. entry := logger.newEntry()
  94. defer logger.releaseEntry(entry)
  95. return entry.WithFields(fields)
  96. }
  97. // Add an error as single field to the log entry. All it does is call
  98. // `WithError` for the given `error`.
  99. func (logger *Logger) WithError(err error) *Entry {
  100. entry := logger.newEntry()
  101. defer logger.releaseEntry(entry)
  102. return entry.WithError(err)
  103. }
  104. // Overrides the time of the log entry.
  105. func (logger *Logger) WithTime(t time.Time) *Entry {
  106. entry := logger.newEntry()
  107. defer logger.releaseEntry(entry)
  108. return entry.WithTime(t)
  109. }
  110. func (logger *Logger) Debugf(format string, args ...interface{}) {
  111. if logger.level() >= DebugLevel {
  112. entry := logger.newEntry()
  113. entry.Debugf(format, args...)
  114. logger.releaseEntry(entry)
  115. }
  116. }
  117. func (logger *Logger) Infof(format string, args ...interface{}) {
  118. if logger.level() >= InfoLevel {
  119. entry := logger.newEntry()
  120. entry.Infof(format, args...)
  121. logger.releaseEntry(entry)
  122. }
  123. }
  124. func (logger *Logger) Printf(format string, args ...interface{}) {
  125. entry := logger.newEntry()
  126. entry.Printf(format, args...)
  127. logger.releaseEntry(entry)
  128. }
  129. func (logger *Logger) Warnf(format string, args ...interface{}) {
  130. if logger.level() >= WarnLevel {
  131. entry := logger.newEntry()
  132. entry.Warnf(format, args...)
  133. logger.releaseEntry(entry)
  134. }
  135. }
  136. func (logger *Logger) Warningf(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. func (logger *Logger) Errorf(format string, args ...interface{}) {
  144. if logger.level() >= ErrorLevel {
  145. entry := logger.newEntry()
  146. entry.Errorf(format, args...)
  147. logger.releaseEntry(entry)
  148. }
  149. }
  150. func (logger *Logger) Fatalf(format string, args ...interface{}) {
  151. if logger.level() >= FatalLevel {
  152. entry := logger.newEntry()
  153. entry.Fatalf(format, args...)
  154. logger.releaseEntry(entry)
  155. }
  156. Exit(1)
  157. }
  158. func (logger *Logger) Panicf(format string, args ...interface{}) {
  159. if logger.level() >= PanicLevel {
  160. entry := logger.newEntry()
  161. entry.Panicf(format, args...)
  162. logger.releaseEntry(entry)
  163. }
  164. }
  165. func (logger *Logger) Debug(args ...interface{}) {
  166. if logger.level() >= DebugLevel {
  167. entry := logger.newEntry()
  168. entry.Debug(args...)
  169. logger.releaseEntry(entry)
  170. }
  171. }
  172. func (logger *Logger) Info(args ...interface{}) {
  173. if logger.level() >= InfoLevel {
  174. entry := logger.newEntry()
  175. entry.Info(args...)
  176. logger.releaseEntry(entry)
  177. }
  178. }
  179. func (logger *Logger) Print(args ...interface{}) {
  180. entry := logger.newEntry()
  181. entry.Info(args...)
  182. logger.releaseEntry(entry)
  183. }
  184. func (logger *Logger) Warn(args ...interface{}) {
  185. if logger.level() >= WarnLevel {
  186. entry := logger.newEntry()
  187. entry.Warn(args...)
  188. logger.releaseEntry(entry)
  189. }
  190. }
  191. func (logger *Logger) Warning(args ...interface{}) {
  192. if logger.level() >= WarnLevel {
  193. entry := logger.newEntry()
  194. entry.Warn(args...)
  195. logger.releaseEntry(entry)
  196. }
  197. }
  198. func (logger *Logger) Error(args ...interface{}) {
  199. if logger.level() >= ErrorLevel {
  200. entry := logger.newEntry()
  201. entry.Error(args...)
  202. logger.releaseEntry(entry)
  203. }
  204. }
  205. func (logger *Logger) Fatal(args ...interface{}) {
  206. if logger.level() >= FatalLevel {
  207. entry := logger.newEntry()
  208. entry.Fatal(args...)
  209. logger.releaseEntry(entry)
  210. }
  211. Exit(1)
  212. }
  213. func (logger *Logger) Panic(args ...interface{}) {
  214. if logger.level() >= PanicLevel {
  215. entry := logger.newEntry()
  216. entry.Panic(args...)
  217. logger.releaseEntry(entry)
  218. }
  219. }
  220. func (logger *Logger) Debugln(args ...interface{}) {
  221. if logger.level() >= DebugLevel {
  222. entry := logger.newEntry()
  223. entry.Debugln(args...)
  224. logger.releaseEntry(entry)
  225. }
  226. }
  227. func (logger *Logger) Infoln(args ...interface{}) {
  228. if logger.level() >= InfoLevel {
  229. entry := logger.newEntry()
  230. entry.Infoln(args...)
  231. logger.releaseEntry(entry)
  232. }
  233. }
  234. func (logger *Logger) Println(args ...interface{}) {
  235. entry := logger.newEntry()
  236. entry.Println(args...)
  237. logger.releaseEntry(entry)
  238. }
  239. func (logger *Logger) Warnln(args ...interface{}) {
  240. if logger.level() >= WarnLevel {
  241. entry := logger.newEntry()
  242. entry.Warnln(args...)
  243. logger.releaseEntry(entry)
  244. }
  245. }
  246. func (logger *Logger) Warningln(args ...interface{}) {
  247. if logger.level() >= WarnLevel {
  248. entry := logger.newEntry()
  249. entry.Warnln(args...)
  250. logger.releaseEntry(entry)
  251. }
  252. }
  253. func (logger *Logger) Errorln(args ...interface{}) {
  254. if logger.level() >= ErrorLevel {
  255. entry := logger.newEntry()
  256. entry.Errorln(args...)
  257. logger.releaseEntry(entry)
  258. }
  259. }
  260. func (logger *Logger) Fatalln(args ...interface{}) {
  261. if logger.level() >= FatalLevel {
  262. entry := logger.newEntry()
  263. entry.Fatalln(args...)
  264. logger.releaseEntry(entry)
  265. }
  266. Exit(1)
  267. }
  268. func (logger *Logger) Panicln(args ...interface{}) {
  269. if logger.level() >= PanicLevel {
  270. entry := logger.newEntry()
  271. entry.Panicln(args...)
  272. logger.releaseEntry(entry)
  273. }
  274. }
  275. //When file is opened with appending mode, it's safe to
  276. //write concurrently to a file (within 4k message on Linux).
  277. //In these cases user can choose to disable the lock.
  278. func (logger *Logger) SetNoLock() {
  279. logger.mu.Disable()
  280. }
  281. func (logger *Logger) level() Level {
  282. return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
  283. }
  284. func (logger *Logger) SetLevel(level Level) {
  285. atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
  286. }
  287. func (logger *Logger) SetOutput(out io.Writer) {
  288. logger.mu.Lock()
  289. defer logger.mu.Unlock()
  290. logger.Out = out
  291. }
  292. func (logger *Logger) AddHook(hook Hook) {
  293. logger.mu.Lock()
  294. defer logger.mu.Unlock()
  295. logger.Hooks.Add(hook)
  296. }