logext.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. package log
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "os"
  7. "runtime"
  8. "strings"
  9. "sync"
  10. "time"
  11. )
  12. // These flags define which text to prefix to each log entry generated by the Logger.
  13. const (
  14. // Bits or'ed together to control what's printed. There is no control over the
  15. // order they appear (the order listed here) or the format they present (as
  16. // described in the comments). A colon appears after these items:
  17. // 2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
  18. Ldate = 1 << iota // the date: 2009/0123
  19. Ltime // the time: 01:23:23
  20. Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
  21. Llongfile // full file name and line number: /a/b/c/d.go:23
  22. Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
  23. Lmodule // module name
  24. Llevel // level: 0(Debug), 1(Info), 2(Warn), 3(Error), 4(Panic), 5(Fatal)
  25. Llongcolor // color will start [info] end of line
  26. Lshortcolor // color only include [info]
  27. LstdFlags = Ldate | Ltime // initial values for the standard logger
  28. //Ldefault = Llevel | LstdFlags | Lshortfile | Llongcolor
  29. ) // [prefix][time][level][module][shortfile|longfile]
  30. func Ldefault() int {
  31. if runtime.GOOS == "windows" {
  32. return Llevel | LstdFlags | Lshortfile
  33. }
  34. return Llevel | LstdFlags | Lshortfile | Llongcolor
  35. }
  36. func Version() string {
  37. return "0.2.0.1121"
  38. }
  39. const (
  40. Lall = iota
  41. )
  42. const (
  43. Ldebug = iota
  44. Linfo
  45. Lwarn
  46. Lerror
  47. Lpanic
  48. Lfatal
  49. Lnone
  50. )
  51. const (
  52. ForeBlack = iota + 30 //30
  53. ForeRed //31
  54. ForeGreen //32
  55. ForeYellow //33
  56. ForeBlue //34
  57. ForePurple //35
  58. ForeCyan //36
  59. ForeWhite //37
  60. )
  61. const (
  62. BackBlack = iota + 40 //40
  63. BackRed //41
  64. BackGreen //42
  65. BackYellow //43
  66. BackBlue //44
  67. BackPurple //45
  68. BackCyan //46
  69. BackWhite //47
  70. )
  71. var levels = []string{
  72. "[Debug]",
  73. "[Info]",
  74. "[Warn]",
  75. "[Error]",
  76. "[Panic]",
  77. "[Fatal]",
  78. }
  79. // MUST called before all logs
  80. func SetLevels(lvs []string) {
  81. levels = lvs
  82. }
  83. var colors = []int{
  84. ForeCyan,
  85. ForeGreen,
  86. ForeYellow,
  87. ForeRed,
  88. ForePurple,
  89. ForeBlue,
  90. }
  91. // MUST called before all logs
  92. func SetColors(cls []int) {
  93. colors = cls
  94. }
  95. // A Logger represents an active logging object that generates lines of
  96. // output to an io.Writer. Each logging operation makes a single call to
  97. // the Writer's Write method. A Logger can be used simultaneously from
  98. // multiple goroutines; it guarantees to serialize access to the Writer.
  99. type Logger struct {
  100. mu sync.Mutex // ensures atomic writes; protects the following fields
  101. prefix string // prefix to write at beginning of each line
  102. flag int // properties
  103. Level int
  104. out io.Writer // destination for output
  105. buf bytes.Buffer // for accumulating text to write
  106. levelStats [6]int64
  107. loc *time.Location
  108. }
  109. // New creates a new Logger. The out variable sets the
  110. // destination to which log data will be written.
  111. // The prefix appears at the beginning of each generated log line.
  112. // The flag argument defines the logging properties.
  113. func New(out io.Writer, prefix string, flag int) *Logger {
  114. l := &Logger{out: out, prefix: prefix, Level: 1, flag: flag, loc: time.Local}
  115. if out != os.Stdout {
  116. l.flag = RmColorFlags(l.flag)
  117. }
  118. return l
  119. }
  120. var Std = New(os.Stderr, "", Ldefault())
  121. // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
  122. // Knows the buffer has capacity.
  123. func itoa(buf *bytes.Buffer, i int, wid int) {
  124. var u uint = uint(i)
  125. if u == 0 && wid <= 1 {
  126. buf.WriteByte('0')
  127. return
  128. }
  129. // Assemble decimal in reverse order.
  130. var b [32]byte
  131. bp := len(b)
  132. for ; u > 0 || wid > 0; u /= 10 {
  133. bp--
  134. wid--
  135. b[bp] = byte(u%10) + '0'
  136. }
  137. // avoid slicing b to avoid an allocation.
  138. for bp < len(b) {
  139. buf.WriteByte(b[bp])
  140. bp++
  141. }
  142. }
  143. func moduleOf(file string) string {
  144. pos := strings.LastIndex(file, "/")
  145. if pos != -1 {
  146. pos1 := strings.LastIndex(file[:pos], "/src/")
  147. if pos1 != -1 {
  148. return file[pos1+5 : pos]
  149. }
  150. }
  151. return "UNKNOWN"
  152. }
  153. func (l *Logger) formatHeader(buf *bytes.Buffer, t time.Time,
  154. file string, line int, lvl int, reqId string) {
  155. if l.prefix != "" {
  156. buf.WriteString(l.prefix)
  157. }
  158. if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
  159. if l.flag&Ldate != 0 {
  160. year, month, day := t.Date()
  161. itoa(buf, year, 4)
  162. buf.WriteByte('/')
  163. itoa(buf, int(month), 2)
  164. buf.WriteByte('/')
  165. itoa(buf, day, 2)
  166. buf.WriteByte(' ')
  167. }
  168. if l.flag&(Ltime|Lmicroseconds) != 0 {
  169. hour, min, sec := t.Clock()
  170. itoa(buf, hour, 2)
  171. buf.WriteByte(':')
  172. itoa(buf, min, 2)
  173. buf.WriteByte(':')
  174. itoa(buf, sec, 2)
  175. if l.flag&Lmicroseconds != 0 {
  176. buf.WriteByte('.')
  177. itoa(buf, t.Nanosecond()/1e3, 6)
  178. }
  179. buf.WriteByte(' ')
  180. }
  181. }
  182. if reqId != "" {
  183. buf.WriteByte('[')
  184. buf.WriteString(reqId)
  185. buf.WriteByte(']')
  186. buf.WriteByte(' ')
  187. }
  188. if l.flag&(Lshortcolor|Llongcolor) != 0 {
  189. buf.WriteString(fmt.Sprintf("\033[1;%dm", colors[lvl]))
  190. }
  191. if l.flag&Llevel != 0 {
  192. buf.WriteString(levels[lvl])
  193. buf.WriteByte(' ')
  194. }
  195. if l.flag&Lshortcolor != 0 {
  196. buf.WriteString("\033[0m")
  197. }
  198. if l.flag&Lmodule != 0 {
  199. buf.WriteByte('[')
  200. buf.WriteString(moduleOf(file))
  201. buf.WriteByte(']')
  202. buf.WriteByte(' ')
  203. }
  204. if l.flag&(Lshortfile|Llongfile) != 0 {
  205. if l.flag&Lshortfile != 0 {
  206. short := file
  207. for i := len(file) - 1; i > 0; i-- {
  208. if file[i] == '/' {
  209. short = file[i+1:]
  210. break
  211. }
  212. }
  213. file = short
  214. }
  215. buf.WriteString(file)
  216. buf.WriteByte(':')
  217. itoa(buf, line, -1)
  218. buf.WriteByte(' ')
  219. }
  220. }
  221. // Output writes the output for a logging event. The string s contains
  222. // the text to print after the prefix specified by the flags of the
  223. // Logger. A newline is appended if the last character of s is not
  224. // already a newline. Calldepth is used to recover the PC and is
  225. // provided for generality, although at the moment on all pre-defined
  226. // paths it will be 2.
  227. func (l *Logger) Output(reqId string, lvl int, calldepth int, s string) error {
  228. if lvl < l.Level {
  229. return nil
  230. }
  231. now := time.Now().In(l.loc) // get this early.
  232. var file string
  233. var line int
  234. l.mu.Lock()
  235. defer l.mu.Unlock()
  236. if l.flag&(Lshortfile|Llongfile|Lmodule) != 0 {
  237. // release lock while getting caller info - it's expensive.
  238. l.mu.Unlock()
  239. var ok bool
  240. _, file, line, ok = runtime.Caller(calldepth)
  241. if !ok {
  242. file = "???"
  243. line = 0
  244. }
  245. l.mu.Lock()
  246. }
  247. l.levelStats[lvl]++
  248. l.buf.Reset()
  249. l.formatHeader(&l.buf, now, file, line, lvl, reqId)
  250. l.buf.WriteString(s)
  251. if l.flag&Llongcolor != 0 {
  252. l.buf.WriteString("\033[0m")
  253. }
  254. if len(s) > 0 && s[len(s)-1] != '\n' {
  255. l.buf.WriteByte('\n')
  256. }
  257. _, err := l.out.Write(l.buf.Bytes())
  258. return err
  259. }
  260. // -----------------------------------------
  261. // Printf calls l.Output to print to the logger.
  262. // Arguments are handled in the manner of fmt.Printf.
  263. func (l *Logger) Printf(format string, v ...interface{}) {
  264. l.Output("", Linfo, 2, fmt.Sprintf(format, v...))
  265. }
  266. // Print calls l.Output to print to the logger.
  267. // Arguments are handled in the manner of fmt.Print.
  268. func (l *Logger) Print(v ...interface{}) {
  269. l.Output("", Linfo, 2, fmt.Sprint(v...))
  270. }
  271. // Println calls l.Output to print to the logger.
  272. // Arguments are handled in the manner of fmt.Println.
  273. func (l *Logger) Println(v ...interface{}) {
  274. l.Output("", Linfo, 2, fmt.Sprintln(v...))
  275. }
  276. // -----------------------------------------
  277. func (l *Logger) Debugf(format string, v ...interface{}) {
  278. l.Output("", Ldebug, 2, fmt.Sprintf(format, v...))
  279. }
  280. func (l *Logger) Debug(v ...interface{}) {
  281. l.Output("", Ldebug, 2, fmt.Sprintln(v...))
  282. }
  283. // -----------------------------------------
  284. func (l *Logger) Infof(format string, v ...interface{}) {
  285. l.Output("", Linfo, 2, fmt.Sprintf(format, v...))
  286. }
  287. func (l *Logger) Info(v ...interface{}) {
  288. l.Output("", Linfo, 2, fmt.Sprintln(v...))
  289. }
  290. // -----------------------------------------
  291. func (l *Logger) Warnf(format string, v ...interface{}) {
  292. l.Output("", Lwarn, 2, fmt.Sprintf(format, v...))
  293. }
  294. func (l *Logger) Warn(v ...interface{}) {
  295. l.Output("", Lwarn, 2, fmt.Sprintln(v...))
  296. }
  297. // -----------------------------------------
  298. func (l *Logger) Errorf(format string, v ...interface{}) {
  299. l.Output("", Lerror, 2, fmt.Sprintf(format, v...))
  300. }
  301. func (l *Logger) Error(v ...interface{}) {
  302. l.Output("", Lerror, 2, fmt.Sprintln(v...))
  303. }
  304. // -----------------------------------------
  305. func (l *Logger) Fatal(v ...interface{}) {
  306. l.Output("", Lfatal, 2, fmt.Sprintln(v...))
  307. os.Exit(1)
  308. }
  309. // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
  310. func (l *Logger) Fatalf(format string, v ...interface{}) {
  311. l.Output("", Lfatal, 2, fmt.Sprintf(format, v...))
  312. os.Exit(1)
  313. }
  314. // -----------------------------------------
  315. // Panic is equivalent to l.Print() followed by a call to panic().
  316. func (l *Logger) Panic(v ...interface{}) {
  317. s := fmt.Sprintln(v...)
  318. l.Output("", Lpanic, 2, s)
  319. panic(s)
  320. }
  321. // Panicf is equivalent to l.Printf() followed by a call to panic().
  322. func (l *Logger) Panicf(format string, v ...interface{}) {
  323. s := fmt.Sprintf(format, v...)
  324. l.Output("", Lpanic, 2, s)
  325. panic(s)
  326. }
  327. // -----------------------------------------
  328. func (l *Logger) Stack(v ...interface{}) {
  329. s := fmt.Sprint(v...)
  330. s += "\n"
  331. buf := make([]byte, 1024*1024)
  332. n := runtime.Stack(buf, true)
  333. s += string(buf[:n])
  334. s += "\n"
  335. l.Output("", Lerror, 2, s)
  336. }
  337. // -----------------------------------------
  338. func (l *Logger) Stat() (stats []int64) {
  339. l.mu.Lock()
  340. v := l.levelStats
  341. l.mu.Unlock()
  342. return v[:]
  343. }
  344. // Flags returns the output flags for the logger.
  345. func (l *Logger) Flags() int {
  346. l.mu.Lock()
  347. defer l.mu.Unlock()
  348. return l.flag
  349. }
  350. func RmColorFlags(flag int) int {
  351. // for un std out, it should not show color since almost them don't support
  352. if flag&Llongcolor != 0 {
  353. flag = flag ^ Llongcolor
  354. }
  355. if flag&Lshortcolor != 0 {
  356. flag = flag ^ Lshortcolor
  357. }
  358. return flag
  359. }
  360. func (l *Logger) Location() *time.Location {
  361. return l.loc
  362. }
  363. func (l *Logger) SetLocation(loc *time.Location) {
  364. l.loc = loc
  365. }
  366. // SetFlags sets the output flags for the logger.
  367. func (l *Logger) SetFlags(flag int) {
  368. l.mu.Lock()
  369. defer l.mu.Unlock()
  370. if l.out != os.Stdout {
  371. flag = RmColorFlags(flag)
  372. }
  373. l.flag = flag
  374. }
  375. // Prefix returns the output prefix for the logger.
  376. func (l *Logger) Prefix() string {
  377. l.mu.Lock()
  378. defer l.mu.Unlock()
  379. return l.prefix
  380. }
  381. // SetPrefix sets the output prefix for the logger.
  382. func (l *Logger) SetPrefix(prefix string) {
  383. l.mu.Lock()
  384. defer l.mu.Unlock()
  385. l.prefix = prefix
  386. }
  387. // SetOutputLevel sets the output level for the logger.
  388. func (l *Logger) SetOutputLevel(lvl int) {
  389. l.mu.Lock()
  390. defer l.mu.Unlock()
  391. l.Level = lvl
  392. }
  393. func (l *Logger) OutputLevel() int {
  394. return l.Level
  395. }
  396. func (l *Logger) SetOutput(w io.Writer) {
  397. l.mu.Lock()
  398. defer l.mu.Unlock()
  399. l.out = w
  400. if w != os.Stdout {
  401. l.flag = RmColorFlags(l.flag)
  402. }
  403. }
  404. // SetOutput sets the output destination for the standard logger.
  405. func SetOutput(w io.Writer) {
  406. Std.SetOutput(w)
  407. }
  408. func SetLocation(loc *time.Location) {
  409. Std.SetLocation(loc)
  410. }
  411. func Location() *time.Location {
  412. return Std.Location()
  413. }
  414. // Flags returns the output flags for the standard logger.
  415. func Flags() int {
  416. return Std.Flags()
  417. }
  418. // SetFlags sets the output flags for the standard logger.
  419. func SetFlags(flag int) {
  420. Std.SetFlags(flag)
  421. }
  422. // Prefix returns the output prefix for the standard logger.
  423. func Prefix() string {
  424. return Std.Prefix()
  425. }
  426. // SetPrefix sets the output prefix for the standard logger.
  427. func SetPrefix(prefix string) {
  428. Std.SetPrefix(prefix)
  429. }
  430. func SetOutputLevel(lvl int) {
  431. Std.SetOutputLevel(lvl)
  432. }
  433. func OutputLevel() int {
  434. return Std.OutputLevel()
  435. }
  436. // -----------------------------------------
  437. // Print calls Output to print to the standard logger.
  438. // Arguments are handled in the manner of fmt.Print.
  439. func Print(v ...interface{}) {
  440. Std.Output("", Linfo, 2, fmt.Sprintln(v...))
  441. }
  442. // Printf calls Output to print to the standard logger.
  443. // Arguments are handled in the manner of fmt.Printf.
  444. func Printf(format string, v ...interface{}) {
  445. Std.Output("", Linfo, 2, fmt.Sprintf(format, v...))
  446. }
  447. // Println calls Output to print to the standard logger.
  448. // Arguments are handled in the manner of fmt.Println.
  449. func Println(v ...interface{}) {
  450. Std.Output("", Linfo, 2, fmt.Sprintln(v...))
  451. }
  452. // -----------------------------------------
  453. func Debugf(format string, v ...interface{}) {
  454. Std.Output("", Ldebug, 2, fmt.Sprintf(format, v...))
  455. }
  456. func Debug(v ...interface{}) {
  457. Std.Output("", Ldebug, 2, fmt.Sprintln(v...))
  458. }
  459. // -----------------------------------------
  460. func Infof(format string, v ...interface{}) {
  461. Std.Output("", Linfo, 2, fmt.Sprintf(format, v...))
  462. }
  463. func Info(v ...interface{}) {
  464. Std.Output("", Linfo, 2, fmt.Sprintln(v...))
  465. }
  466. // -----------------------------------------
  467. func Warnf(format string, v ...interface{}) {
  468. Std.Output("", Lwarn, 2, fmt.Sprintf(format, v...))
  469. }
  470. func Warn(v ...interface{}) {
  471. Std.Output("", Lwarn, 2, fmt.Sprintln(v...))
  472. }
  473. // -----------------------------------------
  474. func Errorf(format string, v ...interface{}) {
  475. Std.Output("", Lerror, 2, fmt.Sprintf(format, v...))
  476. }
  477. func Error(v ...interface{}) {
  478. Std.Output("", Lerror, 2, fmt.Sprintln(v...))
  479. }
  480. // -----------------------------------------
  481. // Fatal is equivalent to Print() followed by a call to os.Exit(1).
  482. func Fatal(v ...interface{}) {
  483. Std.Output("", Lfatal, 2, fmt.Sprintln(v...))
  484. }
  485. // Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
  486. func Fatalf(format string, v ...interface{}) {
  487. Std.Output("", Lfatal, 2, fmt.Sprintf(format, v...))
  488. }
  489. // -----------------------------------------
  490. // Panic is equivalent to Print() followed by a call to panic().
  491. func Panic(v ...interface{}) {
  492. Std.Output("", Lpanic, 2, fmt.Sprintln(v...))
  493. }
  494. // Panicf is equivalent to Printf() followed by a call to panic().
  495. func Panicf(format string, v ...interface{}) {
  496. Std.Output("", Lpanic, 2, fmt.Sprintf(format, v...))
  497. }
  498. // -----------------------------------------
  499. func Stack(v ...interface{}) {
  500. s := fmt.Sprint(v...)
  501. s += "\n"
  502. buf := make([]byte, 1024*1024)
  503. n := runtime.Stack(buf, true)
  504. s += string(buf[:n])
  505. s += "\n"
  506. Std.Output("", Lerror, 2, s)
  507. }
  508. // -----------------------------------------