logger.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
  2. // is governed by an MIT-style license that can be found in the LICENSE file.
  3. // Package logger implements a standardized logger with callback functionality
  4. package logger
  5. import (
  6. "fmt"
  7. "io/ioutil"
  8. "log"
  9. "os"
  10. "strings"
  11. "sync"
  12. )
  13. type LogLevel int
  14. const (
  15. LevelDebug LogLevel = iota
  16. LevelVerbose
  17. LevelInfo
  18. LevelOK
  19. LevelWarn
  20. LevelFatal
  21. NumLevels
  22. )
  23. // A MessageHandler is called with the log level and message text.
  24. type MessageHandler func(l LogLevel, msg string)
  25. type Logger struct {
  26. logger *log.Logger
  27. handlers [NumLevels][]MessageHandler
  28. mut sync.Mutex
  29. }
  30. // The default logger logs to standard output with a time prefix.
  31. var DefaultLogger = New()
  32. func New() *Logger {
  33. if os.Getenv("LOGGER_DISCARD") != "" {
  34. // Hack to completely disable logging, for example when running benchmarks.
  35. return &Logger{
  36. logger: log.New(ioutil.Discard, "", 0),
  37. }
  38. }
  39. return &Logger{
  40. logger: log.New(os.Stdout, "", log.Ltime),
  41. }
  42. }
  43. // AddHandler registers a new MessageHandler to receive messages with the
  44. // specified log level or above.
  45. func (l *Logger) AddHandler(level LogLevel, h MessageHandler) {
  46. l.mut.Lock()
  47. defer l.mut.Unlock()
  48. l.handlers[level] = append(l.handlers[level], h)
  49. }
  50. // See log.SetFlags
  51. func (l *Logger) SetFlags(flag int) {
  52. l.logger.SetFlags(flag)
  53. }
  54. // See log.SetPrefix
  55. func (l *Logger) SetPrefix(prefix string) {
  56. l.logger.SetPrefix(prefix)
  57. }
  58. func (l *Logger) callHandlers(level LogLevel, s string) {
  59. for _, h := range l.handlers[level] {
  60. h(level, strings.TrimSpace(s))
  61. }
  62. }
  63. // Debugln logs a line with a DEBUG prefix.
  64. func (l *Logger) Debugln(vals ...interface{}) {
  65. l.mut.Lock()
  66. defer l.mut.Unlock()
  67. s := fmt.Sprintln(vals...)
  68. l.logger.Output(2, "DEBUG: "+s)
  69. l.callHandlers(LevelDebug, s)
  70. }
  71. // Debugf logs a formatted line with a DEBUG prefix.
  72. func (l *Logger) Debugf(format string, vals ...interface{}) {
  73. l.mut.Lock()
  74. defer l.mut.Unlock()
  75. s := fmt.Sprintf(format, vals...)
  76. l.logger.Output(2, "DEBUG: "+s)
  77. l.callHandlers(LevelDebug, s)
  78. }
  79. // Infoln logs a line with a VERBOSE prefix.
  80. func (l *Logger) Verboseln(vals ...interface{}) {
  81. l.mut.Lock()
  82. defer l.mut.Unlock()
  83. s := fmt.Sprintln(vals...)
  84. l.logger.Output(2, "VERBOSE: "+s)
  85. l.callHandlers(LevelVerbose, s)
  86. }
  87. // Infof logs a formatted line with a VERBOSE prefix.
  88. func (l *Logger) Verbosef(format string, vals ...interface{}) {
  89. l.mut.Lock()
  90. defer l.mut.Unlock()
  91. s := fmt.Sprintf(format, vals...)
  92. l.logger.Output(2, "VERBOSE: "+s)
  93. l.callHandlers(LevelVerbose, s)
  94. }
  95. // Infoln logs a line with an INFO prefix.
  96. func (l *Logger) Infoln(vals ...interface{}) {
  97. l.mut.Lock()
  98. defer l.mut.Unlock()
  99. s := fmt.Sprintln(vals...)
  100. l.logger.Output(2, "INFO: "+s)
  101. l.callHandlers(LevelInfo, s)
  102. }
  103. // Infof logs a formatted line with an INFO prefix.
  104. func (l *Logger) Infof(format string, vals ...interface{}) {
  105. l.mut.Lock()
  106. defer l.mut.Unlock()
  107. s := fmt.Sprintf(format, vals...)
  108. l.logger.Output(2, "INFO: "+s)
  109. l.callHandlers(LevelInfo, s)
  110. }
  111. // Okln logs a line with an OK prefix.
  112. func (l *Logger) Okln(vals ...interface{}) {
  113. l.mut.Lock()
  114. defer l.mut.Unlock()
  115. s := fmt.Sprintln(vals...)
  116. l.logger.Output(2, "OK: "+s)
  117. l.callHandlers(LevelOK, s)
  118. }
  119. // Okf logs a formatted line with an OK prefix.
  120. func (l *Logger) Okf(format string, vals ...interface{}) {
  121. l.mut.Lock()
  122. defer l.mut.Unlock()
  123. s := fmt.Sprintf(format, vals...)
  124. l.logger.Output(2, "OK: "+s)
  125. l.callHandlers(LevelOK, s)
  126. }
  127. // Warnln logs a formatted line with a WARNING prefix.
  128. func (l *Logger) Warnln(vals ...interface{}) {
  129. l.mut.Lock()
  130. defer l.mut.Unlock()
  131. s := fmt.Sprintln(vals...)
  132. l.logger.Output(2, "WARNING: "+s)
  133. l.callHandlers(LevelWarn, s)
  134. }
  135. // Warnf logs a formatted line with a WARNING prefix.
  136. func (l *Logger) Warnf(format string, vals ...interface{}) {
  137. l.mut.Lock()
  138. defer l.mut.Unlock()
  139. s := fmt.Sprintf(format, vals...)
  140. l.logger.Output(2, "WARNING: "+s)
  141. l.callHandlers(LevelWarn, s)
  142. }
  143. // Fatalln logs a line with a FATAL prefix and exits the process with exit
  144. // code 1.
  145. func (l *Logger) Fatalln(vals ...interface{}) {
  146. l.mut.Lock()
  147. defer l.mut.Unlock()
  148. s := fmt.Sprintln(vals...)
  149. l.logger.Output(2, "FATAL: "+s)
  150. l.callHandlers(LevelFatal, s)
  151. os.Exit(1)
  152. }
  153. // Fatalf logs a formatted line with a FATAL prefix and exits the process with
  154. // exit code 1.
  155. func (l *Logger) Fatalf(format string, vals ...interface{}) {
  156. l.mut.Lock()
  157. defer l.mut.Unlock()
  158. s := fmt.Sprintf(format, vals...)
  159. l.logger.Output(2, "FATAL: "+s)
  160. l.callHandlers(LevelFatal, s)
  161. os.Exit(1)
  162. }