You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

323 lines
7.9 KiB

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