log.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. package log
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "path"
  7. "runtime"
  8. "sync"
  9. "time"
  10. "strconv"
  11. "github.com/mattn/go-colorable"
  12. "github.com/mattn/go-isatty"
  13. "github.com/valyala/fasttemplate"
  14. "github.com/labstack/gommon/color"
  15. )
  16. type (
  17. Logger struct {
  18. prefix string
  19. level uint8
  20. output io.Writer
  21. template *fasttemplate.Template
  22. levels []string
  23. color color.Color
  24. mutex sync.Mutex
  25. }
  26. )
  27. const (
  28. DEBUG = iota
  29. INFO
  30. WARN
  31. ERROR
  32. FATAL
  33. OFF
  34. )
  35. var (
  36. global = New("-")
  37. defaultFormat = "time=${time_rfc3339}, level=${level}, prefix=${prefix}, file=${short_file}, " +
  38. "line=${line}, ${message}\n"
  39. )
  40. func New(prefix string) (l *Logger) {
  41. l = &Logger{
  42. level: INFO,
  43. prefix: prefix,
  44. template: l.newTemplate(defaultFormat),
  45. }
  46. l.SetOutput(colorable.NewColorableStdout())
  47. return
  48. }
  49. func (l *Logger) initLevels() {
  50. l.levels = []string{
  51. l.color.Blue("DEBUG"),
  52. l.color.Green("INFO"),
  53. l.color.Yellow("WARN"),
  54. l.color.Red("ERROR"),
  55. l.color.RedBg("FATAL"),
  56. }
  57. }
  58. func (l *Logger) newTemplate(format string) *fasttemplate.Template {
  59. return fasttemplate.New(format, "${", "}")
  60. }
  61. func (l *Logger) DisableColor() {
  62. l.color.Disable()
  63. l.initLevels()
  64. }
  65. func (l *Logger) EnableColor() {
  66. l.color.Enable()
  67. l.initLevels()
  68. }
  69. func (l *Logger) Prefix() string {
  70. return l.prefix
  71. }
  72. func (l *Logger) SetPrefix(p string) {
  73. l.prefix = p
  74. }
  75. func (l *Logger) Level() uint8 {
  76. return l.level
  77. }
  78. func (l *Logger) SetLevel(v uint8) {
  79. l.level = v
  80. }
  81. func (l *Logger) Output() io.Writer {
  82. return l.output
  83. }
  84. func (l *Logger) SetFormat(f string) {
  85. l.template = l.newTemplate(f)
  86. }
  87. func (l *Logger) SetOutput(w io.Writer) {
  88. l.output = w
  89. l.DisableColor()
  90. if w, ok := w.(*os.File); ok && isatty.IsTerminal(w.Fd()) {
  91. l.EnableColor()
  92. }
  93. }
  94. func (l *Logger) Print(i ...interface{}) {
  95. fmt.Fprintln(l.output, i...)
  96. }
  97. func (l *Logger) Printf(format string, args ...interface{}) {
  98. f := fmt.Sprintf("%s\n", format)
  99. fmt.Fprintf(l.output, f, args...)
  100. }
  101. func (l *Logger) Debug(i ...interface{}) {
  102. l.log(DEBUG, "", i...)
  103. }
  104. func (l *Logger) Debugf(format string, args ...interface{}) {
  105. l.log(DEBUG, format, args...)
  106. }
  107. func (l *Logger) Info(i ...interface{}) {
  108. l.log(INFO, "", i...)
  109. }
  110. func (l *Logger) Infof(format string, args ...interface{}) {
  111. l.log(INFO, format, args...)
  112. }
  113. func (l *Logger) Warn(i ...interface{}) {
  114. l.log(WARN, "", i...)
  115. }
  116. func (l *Logger) Warnf(format string, args ...interface{}) {
  117. l.log(WARN, format, args...)
  118. }
  119. func (l *Logger) Error(i ...interface{}) {
  120. l.log(ERROR, "", i...)
  121. }
  122. func (l *Logger) Errorf(format string, args ...interface{}) {
  123. l.log(ERROR, format, args...)
  124. }
  125. func (l *Logger) Fatal(i ...interface{}) {
  126. l.log(FATAL, "", i...)
  127. os.Exit(1)
  128. }
  129. func (l *Logger) Fatalf(format string, args ...interface{}) {
  130. l.log(FATAL, format, args...)
  131. os.Exit(1)
  132. }
  133. func DisableColor() {
  134. global.DisableColor()
  135. }
  136. func EnableColor() {
  137. global.EnableColor()
  138. }
  139. func Prefix() string {
  140. return global.Prefix()
  141. }
  142. func SetPrefix(p string) {
  143. global.SetPrefix(p)
  144. }
  145. func Level() uint8 {
  146. return global.Level()
  147. }
  148. func SetLevel(v uint8) {
  149. global.SetLevel(v)
  150. }
  151. func Output() io.Writer {
  152. return global.Output()
  153. }
  154. func SetOutput(w io.Writer) {
  155. global.SetOutput(w)
  156. }
  157. func SetFormat(f string) {
  158. global.SetFormat(f)
  159. }
  160. func Print(i ...interface{}) {
  161. global.Print(i...)
  162. }
  163. func Printf(format string, args ...interface{}) {
  164. global.Printf(format, args...)
  165. }
  166. func Debug(i ...interface{}) {
  167. global.Debug(i...)
  168. }
  169. func Debugf(format string, args ...interface{}) {
  170. global.Debugf(format, args...)
  171. }
  172. func Info(i ...interface{}) {
  173. global.Info(i...)
  174. }
  175. func Infof(format string, args ...interface{}) {
  176. global.Infof(format, args...)
  177. }
  178. func Warn(i ...interface{}) {
  179. global.Warn(i...)
  180. }
  181. func Warnf(format string, args ...interface{}) {
  182. global.Warnf(format, args...)
  183. }
  184. func Error(i ...interface{}) {
  185. global.Error(i...)
  186. }
  187. func Errorf(format string, args ...interface{}) {
  188. global.Errorf(format, args...)
  189. }
  190. func Fatal(i ...interface{}) {
  191. global.Fatal(i...)
  192. }
  193. func Fatalf(format string, args ...interface{}) {
  194. global.Fatalf(format, args...)
  195. }
  196. func (l *Logger) log(v uint8, format string, args ...interface{}) {
  197. l.mutex.Lock()
  198. defer l.mutex.Unlock()
  199. _, file, line, _ := runtime.Caller(3)
  200. if v >= l.level {
  201. message := ""
  202. if format == "" {
  203. message = fmt.Sprint(args...)
  204. } else {
  205. message = fmt.Sprintf(format, args...)
  206. }
  207. l.template.ExecuteFunc(l.output, func(w io.Writer, tag string) (int, error) {
  208. switch tag {
  209. case "time_rfc3339":
  210. return w.Write([]byte(time.Now().Format(time.RFC3339)))
  211. case "level":
  212. return w.Write([]byte(l.levels[v]))
  213. case "prefix":
  214. return w.Write([]byte(l.prefix))
  215. case "long_file":
  216. return w.Write([]byte(file))
  217. case "short_file":
  218. return w.Write([]byte(path.Base(file)))
  219. case "line":
  220. return w.Write([]byte(strconv.Itoa(line)))
  221. case "message":
  222. return w.Write([]byte(message))
  223. default:
  224. return w.Write([]byte(fmt.Sprintf("[unknown tag %s]", tag)))
  225. }
  226. })
  227. }
  228. }