logger.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. package log
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. "runtime"
  7. "strconv"
  8. "strings"
  9. "sync"
  10. "time"
  11. "github.com/siddontang/go-log/loggers"
  12. )
  13. const (
  14. timeFormat = "2006/01/02 15:04:05"
  15. maxBufPoolSize = 16
  16. )
  17. // Logger flag
  18. const (
  19. Ltime = 1 << iota // time format "2006/01/02 15:04:05"
  20. Lfile // file.go:123
  21. Llevel // [Trace|Debug|Info...]
  22. )
  23. // Level type
  24. type Level int
  25. // Log level, from low to high, more high means more serious
  26. const (
  27. LevelTrace Level = iota
  28. LevelDebug
  29. LevelInfo
  30. LevelWarn
  31. LevelError
  32. LevelFatal
  33. )
  34. // String returns level String
  35. func (l Level) String() string {
  36. switch l {
  37. case LevelTrace:
  38. return "trace"
  39. case LevelDebug:
  40. return "debug"
  41. case LevelInfo:
  42. return "info"
  43. case LevelWarn:
  44. return "warn"
  45. case LevelError:
  46. return "error"
  47. case LevelFatal:
  48. return "fatal"
  49. }
  50. // return default info
  51. return "info"
  52. }
  53. // Logger is the logger to record log
  54. type Logger struct {
  55. // TODO: support logger.Contextual
  56. loggers.Advanced
  57. level Level
  58. flag int
  59. hLock sync.Mutex
  60. handler Handler
  61. bufs sync.Pool
  62. }
  63. // New creates a logger with specified handler and flag
  64. func New(handler Handler, flag int) *Logger {
  65. var l = new(Logger)
  66. l.level = LevelInfo
  67. l.handler = handler
  68. l.flag = flag
  69. l.bufs = sync.Pool{
  70. New: func() interface{} {
  71. return make([]byte, 0, 1024)
  72. },
  73. }
  74. return l
  75. }
  76. // NewDefault creates default logger with specified handler and flag: Ltime|Lfile|Llevel
  77. func NewDefault(handler Handler) *Logger {
  78. return New(handler, Ltime|Lfile|Llevel)
  79. }
  80. func newStdHandler() *StreamHandler {
  81. h, _ := NewStreamHandler(os.Stdout)
  82. return h
  83. }
  84. // Close closes the logger
  85. func (l *Logger) Close() {
  86. l.hLock.Lock()
  87. defer l.hLock.Unlock()
  88. l.handler.Close()
  89. }
  90. // SetLevel sets log level, any log level less than it will not log
  91. func (l *Logger) SetLevel(level Level) {
  92. l.level = level
  93. }
  94. // SetLevelByName sets log level by name
  95. func (l *Logger) SetLevelByName(name string) {
  96. level := LevelInfo
  97. switch strings.ToLower(name) {
  98. case "trace":
  99. level = LevelTrace
  100. case "debug":
  101. level = LevelDebug
  102. case "warn", "warning":
  103. level = LevelWarn
  104. case "error":
  105. level = LevelError
  106. case "fatal":
  107. level = LevelFatal
  108. default:
  109. level = LevelInfo
  110. }
  111. l.SetLevel(level)
  112. }
  113. // Output records the log with special callstack depth and log level.
  114. func (l *Logger) Output(callDepth int, level Level, msg string) {
  115. if l.level > level {
  116. return
  117. }
  118. buf := l.bufs.Get().([]byte)
  119. buf = buf[0:0]
  120. defer l.bufs.Put(buf)
  121. if l.flag&Ltime > 0 {
  122. now := time.Now().Format(timeFormat)
  123. buf = append(buf, '[')
  124. buf = append(buf, now...)
  125. buf = append(buf, "] "...)
  126. }
  127. if l.flag&Llevel > 0 {
  128. buf = append(buf, '[')
  129. buf = append(buf, level.String()...)
  130. buf = append(buf, "] "...)
  131. }
  132. if l.flag&Lfile > 0 {
  133. _, file, line, ok := runtime.Caller(callDepth)
  134. if !ok {
  135. file = "???"
  136. line = 0
  137. } else {
  138. for i := len(file) - 1; i > 0; i-- {
  139. if file[i] == '/' {
  140. file = file[i+1:]
  141. break
  142. }
  143. }
  144. }
  145. buf = append(buf, file...)
  146. buf = append(buf, ':')
  147. buf = strconv.AppendInt(buf, int64(line), 10)
  148. buf = append(buf, ' ')
  149. }
  150. buf = append(buf, msg...)
  151. if len(msg) == 0 || msg[len(msg)-1] != '\n' {
  152. buf = append(buf, '\n')
  153. }
  154. l.hLock.Lock()
  155. l.handler.Write(buf)
  156. l.hLock.Unlock()
  157. }
  158. // Output json format records the log with special callstack depth and log level.
  159. func (l *Logger) OutputJson(callDepth int, level Level, body interface{}) {
  160. if l.level > level {
  161. return
  162. }
  163. buf := l.bufs.Get().([]byte)
  164. buf = buf[0:0]
  165. defer l.bufs.Put(buf)
  166. type JsonLog struct {
  167. Time string `json:"log_time"`
  168. Level string `json:"log_level"`
  169. File string `json:"log_file"`
  170. Line string `json:"log_line"`
  171. Body interface{} `json:"log_body"`
  172. }
  173. var jsonlog JsonLog
  174. if l.flag&Ltime > 0 {
  175. now := time.Now().Format(timeFormat)
  176. jsonlog.Time = now
  177. }
  178. if l.flag&Llevel > 0 {
  179. jsonlog.Level = level.String()
  180. }
  181. if l.flag&Lfile > 0 {
  182. _, file, line, ok := runtime.Caller(callDepth)
  183. if !ok {
  184. file = "???"
  185. line = 0
  186. } else {
  187. for i := len(file) - 1; i > 0; i-- {
  188. if file[i] == '/' {
  189. file = file[i+1:]
  190. break
  191. }
  192. }
  193. }
  194. jsonlog.File = file
  195. jsonlog.Line = string(strconv.AppendInt(buf, int64(line), 10))
  196. }
  197. jsonlog.Body = body
  198. msg, _ := json.Marshal(jsonlog)
  199. msg = append(msg, '\n')
  200. l.hLock.Lock()
  201. l.handler.Write(msg)
  202. l.hLock.Unlock()
  203. }
  204. // Fatal records the log with fatal level and exits
  205. func (l *Logger) Fatal(args ...interface{}) {
  206. l.Output(2, LevelFatal, fmt.Sprint(args...))
  207. os.Exit(1)
  208. }
  209. // Fatalf records the log with fatal level and exits
  210. func (l *Logger) Fatalf(format string, args ...interface{}) {
  211. l.Output(2, LevelFatal, fmt.Sprintf(format, args...))
  212. os.Exit(1)
  213. }
  214. // Fatalln records the log with fatal level and exits
  215. func (l *Logger) Fatalln(args ...interface{}) {
  216. l.Output(2, LevelFatal, fmt.Sprintln(args...))
  217. os.Exit(1)
  218. }
  219. // Panic records the log with fatal level and panics
  220. func (l *Logger) Panic(args ...interface{}) {
  221. msg := fmt.Sprint(args...)
  222. l.Output(2, LevelError, msg)
  223. panic(msg)
  224. }
  225. // Panicf records the log with fatal level and panics
  226. func (l *Logger) Panicf(format string, args ...interface{}) {
  227. msg := fmt.Sprintf(format, args...)
  228. l.Output(2, LevelError, msg)
  229. panic(msg)
  230. }
  231. // Panicln records the log with fatal level and panics
  232. func (l *Logger) Panicln(args ...interface{}) {
  233. msg := fmt.Sprintln(args...)
  234. l.Output(2, LevelError, msg)
  235. panic(msg)
  236. }
  237. // Print records the log with trace level
  238. func (l *Logger) Print(args ...interface{}) {
  239. l.Output(2, LevelTrace, fmt.Sprint(args...))
  240. }
  241. // Printf records the log with trace level
  242. func (l *Logger) Printf(format string, args ...interface{}) {
  243. l.Output(2, LevelTrace, fmt.Sprintf(format, args...))
  244. }
  245. // Println records the log with trace level
  246. func (l *Logger) Println(args ...interface{}) {
  247. l.Output(2, LevelTrace, fmt.Sprintln(args...))
  248. }
  249. // Debug records the log with debug level
  250. func (l *Logger) Debug(args ...interface{}) {
  251. l.Output(2, LevelDebug, fmt.Sprint(args...))
  252. }
  253. // Debugf records the log with debug level
  254. func (l *Logger) Debugf(format string, args ...interface{}) {
  255. l.Output(2, LevelDebug, fmt.Sprintf(format, args...))
  256. }
  257. // Debugln records the log with debug level
  258. func (l *Logger) Debugln(args ...interface{}) {
  259. l.Output(2, LevelDebug, fmt.Sprintln(args...))
  260. }
  261. // Error records the log with error level
  262. func (l *Logger) Error(args ...interface{}) {
  263. l.Output(2, LevelError, fmt.Sprint(args...))
  264. }
  265. // Errorf records the log with error level
  266. func (l *Logger) Errorf(format string, args ...interface{}) {
  267. l.Output(2, LevelError, fmt.Sprintf(format, args...))
  268. }
  269. // Errorln records the log with error level
  270. func (l *Logger) Errorln(args ...interface{}) {
  271. l.Output(2, LevelError, fmt.Sprintln(args...))
  272. }
  273. // Info records the log with info level
  274. func (l *Logger) Info(args ...interface{}) {
  275. l.Output(2, LevelInfo, fmt.Sprint(args...))
  276. }
  277. // Infof records the log with info level
  278. func (l *Logger) Infof(format string, args ...interface{}) {
  279. l.Output(2, LevelInfo, fmt.Sprintf(format, args...))
  280. }
  281. // Infoln records the log with info level
  282. func (l *Logger) Infoln(args ...interface{}) {
  283. l.Output(2, LevelInfo, fmt.Sprintln(args...))
  284. }
  285. // Warn records the log with warn level
  286. func (l *Logger) Warn(args ...interface{}) {
  287. l.Output(2, LevelWarn, fmt.Sprint(args...))
  288. }
  289. // Warnf records the log with warn level
  290. func (l *Logger) Warnf(format string, args ...interface{}) {
  291. l.Output(2, LevelWarn, fmt.Sprintf(format, args...))
  292. }
  293. // Warnln records the log with warn level
  294. func (l *Logger) Warnln(args ...interface{}) {
  295. l.Output(2, LevelWarn, fmt.Sprintln(args...))
  296. }