log.go 5.4 KB

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