logger.go 7.5 KB

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