logger.go 10 KB

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