log.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. package log
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "os"
  8. "path"
  9. "runtime"
  10. "strconv"
  11. "sync"
  12. "sync/atomic"
  13. "time"
  14. "github.com/mattn/go-isatty"
  15. "github.com/valyala/fasttemplate"
  16. "github.com/labstack/gommon/color"
  17. )
  18. type (
  19. Logger struct {
  20. prefix string
  21. level uint32
  22. skip int
  23. output io.Writer
  24. template *fasttemplate.Template
  25. levels []string
  26. color *color.Color
  27. bufferPool sync.Pool
  28. mutex sync.Mutex
  29. }
  30. Lvl uint8
  31. JSON map[string]interface{}
  32. )
  33. const (
  34. DEBUG Lvl = iota + 1
  35. INFO
  36. WARN
  37. ERROR
  38. OFF
  39. panicLevel
  40. fatalLevel
  41. )
  42. var (
  43. global = New("-")
  44. defaultHeader = `{"time":"${time_rfc3339_nano}","level":"${level}","prefix":"${prefix}",` +
  45. `"file":"${short_file}","line":"${line}"}`
  46. )
  47. func init() {
  48. global.skip = 3
  49. }
  50. func New(prefix string) (l *Logger) {
  51. l = &Logger{
  52. level: uint32(INFO),
  53. skip: 2,
  54. prefix: prefix,
  55. template: l.newTemplate(defaultHeader),
  56. color: color.New(),
  57. bufferPool: sync.Pool{
  58. New: func() interface{} {
  59. return bytes.NewBuffer(make([]byte, 256))
  60. },
  61. },
  62. }
  63. l.initLevels()
  64. l.SetOutput(output())
  65. return
  66. }
  67. func (l *Logger) initLevels() {
  68. l.levels = []string{
  69. "-",
  70. l.color.Blue("DEBUG"),
  71. l.color.Green("INFO"),
  72. l.color.Yellow("WARN"),
  73. l.color.Red("ERROR"),
  74. "",
  75. l.color.Yellow("PANIC", color.U),
  76. l.color.Red("FATAL", color.U),
  77. }
  78. }
  79. func (l *Logger) newTemplate(format string) *fasttemplate.Template {
  80. return fasttemplate.New(format, "${", "}")
  81. }
  82. func (l *Logger) DisableColor() {
  83. l.color.Disable()
  84. l.initLevels()
  85. }
  86. func (l *Logger) EnableColor() {
  87. l.color.Enable()
  88. l.initLevels()
  89. }
  90. func (l *Logger) Prefix() string {
  91. return l.prefix
  92. }
  93. func (l *Logger) SetPrefix(p string) {
  94. l.prefix = p
  95. }
  96. func (l *Logger) Level() Lvl {
  97. return Lvl(atomic.LoadUint32(&l.level))
  98. }
  99. func (l *Logger) SetLevel(level Lvl) {
  100. atomic.StoreUint32(&l.level, uint32(level))
  101. }
  102. func (l *Logger) Output() io.Writer {
  103. return l.output
  104. }
  105. func (l *Logger) SetOutput(w io.Writer) {
  106. l.output = w
  107. if w, ok := w.(*os.File); !ok || !isatty.IsTerminal(w.Fd()) {
  108. l.DisableColor()
  109. }
  110. }
  111. func (l *Logger) Color() *color.Color {
  112. return l.color
  113. }
  114. func (l *Logger) SetHeader(h string) {
  115. l.template = l.newTemplate(h)
  116. }
  117. func (l *Logger) Print(i ...interface{}) {
  118. l.log(0, "", i...)
  119. // fmt.Fprintln(l.output, i...)
  120. }
  121. func (l *Logger) Printf(format string, args ...interface{}) {
  122. l.log(0, format, args...)
  123. }
  124. func (l *Logger) Printj(j JSON) {
  125. l.log(0, "json", j)
  126. }
  127. func (l *Logger) Debug(i ...interface{}) {
  128. l.log(DEBUG, "", i...)
  129. }
  130. func (l *Logger) Debugf(format string, args ...interface{}) {
  131. l.log(DEBUG, format, args...)
  132. }
  133. func (l *Logger) Debugj(j JSON) {
  134. l.log(DEBUG, "json", j)
  135. }
  136. func (l *Logger) Info(i ...interface{}) {
  137. l.log(INFO, "", i...)
  138. }
  139. func (l *Logger) Infof(format string, args ...interface{}) {
  140. l.log(INFO, format, args...)
  141. }
  142. func (l *Logger) Infoj(j JSON) {
  143. l.log(INFO, "json", j)
  144. }
  145. func (l *Logger) Warn(i ...interface{}) {
  146. l.log(WARN, "", i...)
  147. }
  148. func (l *Logger) Warnf(format string, args ...interface{}) {
  149. l.log(WARN, format, args...)
  150. }
  151. func (l *Logger) Warnj(j JSON) {
  152. l.log(WARN, "json", j)
  153. }
  154. func (l *Logger) Error(i ...interface{}) {
  155. l.log(ERROR, "", i...)
  156. }
  157. func (l *Logger) Errorf(format string, args ...interface{}) {
  158. l.log(ERROR, format, args...)
  159. }
  160. func (l *Logger) Errorj(j JSON) {
  161. l.log(ERROR, "json", j)
  162. }
  163. func (l *Logger) Fatal(i ...interface{}) {
  164. l.log(fatalLevel, "", i...)
  165. os.Exit(1)
  166. }
  167. func (l *Logger) Fatalf(format string, args ...interface{}) {
  168. l.log(fatalLevel, format, args...)
  169. os.Exit(1)
  170. }
  171. func (l *Logger) Fatalj(j JSON) {
  172. l.log(fatalLevel, "json", j)
  173. os.Exit(1)
  174. }
  175. func (l *Logger) Panic(i ...interface{}) {
  176. l.log(panicLevel, "", i...)
  177. panic(fmt.Sprint(i...))
  178. }
  179. func (l *Logger) Panicf(format string, args ...interface{}) {
  180. l.log(panicLevel, format, args...)
  181. panic(fmt.Sprintf(format, args...))
  182. }
  183. func (l *Logger) Panicj(j JSON) {
  184. l.log(panicLevel, "json", j)
  185. panic(j)
  186. }
  187. func DisableColor() {
  188. global.DisableColor()
  189. }
  190. func EnableColor() {
  191. global.EnableColor()
  192. }
  193. func Prefix() string {
  194. return global.Prefix()
  195. }
  196. func SetPrefix(p string) {
  197. global.SetPrefix(p)
  198. }
  199. func Level() Lvl {
  200. return global.Level()
  201. }
  202. func SetLevel(level Lvl) {
  203. global.SetLevel(level)
  204. }
  205. func Output() io.Writer {
  206. return global.Output()
  207. }
  208. func SetOutput(w io.Writer) {
  209. global.SetOutput(w)
  210. }
  211. func SetHeader(h string) {
  212. global.SetHeader(h)
  213. }
  214. func Print(i ...interface{}) {
  215. global.Print(i...)
  216. }
  217. func Printf(format string, args ...interface{}) {
  218. global.Printf(format, args...)
  219. }
  220. func Printj(j JSON) {
  221. global.Printj(j)
  222. }
  223. func Debug(i ...interface{}) {
  224. global.Debug(i...)
  225. }
  226. func Debugf(format string, args ...interface{}) {
  227. global.Debugf(format, args...)
  228. }
  229. func Debugj(j JSON) {
  230. global.Debugj(j)
  231. }
  232. func Info(i ...interface{}) {
  233. global.Info(i...)
  234. }
  235. func Infof(format string, args ...interface{}) {
  236. global.Infof(format, args...)
  237. }
  238. func Infoj(j JSON) {
  239. global.Infoj(j)
  240. }
  241. func Warn(i ...interface{}) {
  242. global.Warn(i...)
  243. }
  244. func Warnf(format string, args ...interface{}) {
  245. global.Warnf(format, args...)
  246. }
  247. func Warnj(j JSON) {
  248. global.Warnj(j)
  249. }
  250. func Error(i ...interface{}) {
  251. global.Error(i...)
  252. }
  253. func Errorf(format string, args ...interface{}) {
  254. global.Errorf(format, args...)
  255. }
  256. func Errorj(j JSON) {
  257. global.Errorj(j)
  258. }
  259. func Fatal(i ...interface{}) {
  260. global.Fatal(i...)
  261. }
  262. func Fatalf(format string, args ...interface{}) {
  263. global.Fatalf(format, args...)
  264. }
  265. func Fatalj(j JSON) {
  266. global.Fatalj(j)
  267. }
  268. func Panic(i ...interface{}) {
  269. global.Panic(i...)
  270. }
  271. func Panicf(format string, args ...interface{}) {
  272. global.Panicf(format, args...)
  273. }
  274. func Panicj(j JSON) {
  275. global.Panicj(j)
  276. }
  277. func (l *Logger) log(level Lvl, format string, args ...interface{}) {
  278. if level >= l.Level() || level == 0 {
  279. buf := l.bufferPool.Get().(*bytes.Buffer)
  280. buf.Reset()
  281. defer l.bufferPool.Put(buf)
  282. _, file, line, _ := runtime.Caller(l.skip)
  283. message := ""
  284. if format == "" {
  285. message = fmt.Sprint(args...)
  286. } else if format == "json" {
  287. b, err := json.Marshal(args[0])
  288. if err != nil {
  289. panic(err)
  290. }
  291. message = string(b)
  292. } else {
  293. message = fmt.Sprintf(format, args...)
  294. }
  295. _, err := l.template.ExecuteFunc(buf, func(w io.Writer, tag string) (int, error) {
  296. switch tag {
  297. case "time_rfc3339":
  298. return w.Write([]byte(time.Now().Format(time.RFC3339)))
  299. case "time_rfc3339_nano":
  300. return w.Write([]byte(time.Now().Format(time.RFC3339Nano)))
  301. case "level":
  302. return w.Write([]byte(l.levels[level]))
  303. case "prefix":
  304. return w.Write([]byte(l.prefix))
  305. case "long_file":
  306. return w.Write([]byte(file))
  307. case "short_file":
  308. return w.Write([]byte(path.Base(file)))
  309. case "line":
  310. return w.Write([]byte(strconv.Itoa(line)))
  311. }
  312. return 0, nil
  313. })
  314. if err == nil {
  315. s := buf.String()
  316. i := buf.Len() - 1
  317. if s[i] == '}' {
  318. // JSON header
  319. buf.Truncate(i)
  320. buf.WriteByte(',')
  321. if format == "json" {
  322. buf.WriteString(message[1:])
  323. } else {
  324. buf.WriteString(`"message":`)
  325. buf.WriteString(strconv.Quote(message))
  326. buf.WriteString(`}`)
  327. }
  328. } else {
  329. // Text header
  330. buf.WriteByte(' ')
  331. buf.WriteString(message)
  332. }
  333. buf.WriteByte('\n')
  334. l.mutex.Lock()
  335. defer l.mutex.Unlock()
  336. l.output.Write(buf.Bytes())
  337. }
  338. }
  339. }