log.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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=${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.initLevels()
  47. l.SetOutput(colorable.NewColorableStdout())
  48. return
  49. }
  50. func (l *Logger) initLevels() {
  51. l.levels = []string{
  52. l.color.Blue("DEBUG"),
  53. l.color.Green("INFO"),
  54. l.color.Yellow("WARN"),
  55. l.color.Red("ERROR"),
  56. l.color.RedBg("FATAL"),
  57. }
  58. }
  59. func (l *Logger) newTemplate(format string) *fasttemplate.Template {
  60. return fasttemplate.New(format, "${", "}")
  61. }
  62. func (l *Logger) DisableColor() {
  63. l.color.Disable()
  64. l.initLevels()
  65. }
  66. func (l *Logger) EnableColor() {
  67. l.color.Enable()
  68. l.initLevels()
  69. }
  70. func (l *Logger) Prefix() string {
  71. return l.prefix
  72. }
  73. func (l *Logger) SetPrefix(p string) {
  74. l.prefix = p
  75. }
  76. func (l *Logger) Level() uint8 {
  77. return l.level
  78. }
  79. func (l *Logger) SetLevel(v uint8) {
  80. l.level = v
  81. }
  82. func (l *Logger) Output() io.Writer {
  83. return l.output
  84. }
  85. func (l *Logger) SetFormat(f string) {
  86. l.template = l.newTemplate(f)
  87. }
  88. func (l *Logger) SetOutput(w io.Writer) {
  89. l.output = w
  90. if w, ok := w.(*os.File); !ok || !isatty.IsTerminal(w.Fd()) {
  91. l.DisableColor()
  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. if v == FATAL {
  208. stack := make([]byte, 4<<10)
  209. length := runtime.Stack(stack, true)
  210. message = message + "\n" + string(stack[:length])
  211. }
  212. l.template.ExecuteFunc(l.output, func(w io.Writer, tag string) (int, error) {
  213. switch tag {
  214. case "time_rfc3339":
  215. return w.Write([]byte(time.Now().Format(time.RFC3339)))
  216. case "level":
  217. return w.Write([]byte(l.levels[v]))
  218. case "prefix":
  219. return w.Write([]byte(l.prefix))
  220. case "long_file":
  221. return w.Write([]byte(file))
  222. case "short_file":
  223. return w.Write([]byte(path.Base(file)))
  224. case "line":
  225. return w.Write([]byte(strconv.Itoa(line)))
  226. case "message":
  227. return w.Write([]byte(message))
  228. default:
  229. return w.Write([]byte(fmt.Sprintf("[unknown tag %s]", tag)))
  230. }
  231. })
  232. }
  233. }