log.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. // Copyright 2014 beego Author. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package logs provide a general log interface
  15. // Usage:
  16. //
  17. // import "github.com/astaxie/beego/logs"
  18. //
  19. // log := NewLogger(10000)
  20. // log.SetLogger("console", "")
  21. //
  22. // > the first params stand for how many channel
  23. //
  24. // Use it like this:
  25. //
  26. // log.Trace("trace")
  27. // log.Info("info")
  28. // log.Warn("warning")
  29. // log.Debug("debug")
  30. // log.Critical("critical")
  31. //
  32. // more docs http://beego.me/docs/module/logs.md
  33. package logs
  34. import (
  35. "fmt"
  36. "log"
  37. "os"
  38. "path"
  39. "runtime"
  40. "strconv"
  41. "strings"
  42. "sync"
  43. "time"
  44. )
  45. // RFC5424 log message levels.
  46. const (
  47. LevelEmergency = iota
  48. LevelAlert
  49. LevelCritical
  50. LevelError
  51. LevelWarning
  52. LevelNotice
  53. LevelInformational
  54. LevelDebug
  55. )
  56. // levelLogLogger is defined to implement log.Logger
  57. // the real log level will be LevelEmergency
  58. const levelLoggerImpl = -1
  59. // Name for adapter with beego official support
  60. const (
  61. AdapterConsole = "console"
  62. AdapterFile = "file"
  63. AdapterMultiFile = "multifile"
  64. AdapterMail = "stmp"
  65. AdapterConn = "conn"
  66. AdapterEs = "es"
  67. )
  68. // Legacy log level constants to ensure backwards compatibility.
  69. const (
  70. LevelInfo = LevelInformational
  71. LevelTrace = LevelDebug
  72. LevelWarn = LevelWarning
  73. )
  74. type newLoggerFunc func() Logger
  75. // Logger defines the behavior of a log provider.
  76. type Logger interface {
  77. Init(config string) error
  78. WriteMsg(when time.Time, msg string, level int) error
  79. Destroy()
  80. Flush()
  81. }
  82. var adapters = make(map[string]newLoggerFunc)
  83. var levelPrefix = [LevelDebug + 1]string{"[M] ", "[A] ", "[C] ", "[E] ", "[W] ", "[N] ", "[I] ", "[D] "}
  84. // Register makes a log provide available by the provided name.
  85. // If Register is called twice with the same name or if driver is nil,
  86. // it panics.
  87. func Register(name string, log newLoggerFunc) {
  88. if log == nil {
  89. panic("logs: Register provide is nil")
  90. }
  91. if _, dup := adapters[name]; dup {
  92. panic("logs: Register called twice for provider " + name)
  93. }
  94. adapters[name] = log
  95. }
  96. // BeeLogger is default logger in beego application.
  97. // it can contain several providers and log message into all providers.
  98. type BeeLogger struct {
  99. lock sync.Mutex
  100. level int
  101. init bool
  102. enableFuncCallDepth bool
  103. loggerFuncCallDepth int
  104. asynchronous bool
  105. msgChanLen int64
  106. msgChan chan *logMsg
  107. signalChan chan string
  108. wg sync.WaitGroup
  109. outputs []*nameLogger
  110. }
  111. const defaultAsyncMsgLen = 1e3
  112. type nameLogger struct {
  113. Logger
  114. name string
  115. }
  116. type logMsg struct {
  117. level int
  118. msg string
  119. when time.Time
  120. }
  121. var logMsgPool *sync.Pool
  122. // NewLogger returns a new BeeLogger.
  123. // channelLen means the number of messages in chan(used where asynchronous is true).
  124. // if the buffering chan is full, logger adapters write to file or other way.
  125. func NewLogger(channelLens ...int64) *BeeLogger {
  126. bl := new(BeeLogger)
  127. bl.level = LevelDebug
  128. bl.loggerFuncCallDepth = 2
  129. bl.msgChanLen = append(channelLens, 0)[0]
  130. if bl.msgChanLen <= 0 {
  131. bl.msgChanLen = defaultAsyncMsgLen
  132. }
  133. bl.signalChan = make(chan string, 1)
  134. bl.setLogger(AdapterConsole)
  135. return bl
  136. }
  137. // Async set the log to asynchronous and start the goroutine
  138. func (bl *BeeLogger) Async(msgLen ...int64) *BeeLogger {
  139. bl.lock.Lock()
  140. defer bl.lock.Unlock()
  141. if bl.asynchronous {
  142. return bl
  143. }
  144. bl.asynchronous = true
  145. if len(msgLen) > 0 && msgLen[0] > 0 {
  146. bl.msgChanLen = msgLen[0]
  147. }
  148. bl.msgChan = make(chan *logMsg, bl.msgChanLen)
  149. logMsgPool = &sync.Pool{
  150. New: func() interface{} {
  151. return &logMsg{}
  152. },
  153. }
  154. bl.wg.Add(1)
  155. go bl.startLogger()
  156. return bl
  157. }
  158. // SetLogger provides a given logger adapter into BeeLogger with config string.
  159. // config need to be correct JSON as string: {"interval":360}.
  160. func (bl *BeeLogger) setLogger(adapterName string, configs ...string) error {
  161. config := append(configs, "{}")[0]
  162. for _, l := range bl.outputs {
  163. if l.name == adapterName {
  164. return fmt.Errorf("logs: duplicate adaptername %q (you have set this logger before)", adapterName)
  165. }
  166. }
  167. log, ok := adapters[adapterName]
  168. if !ok {
  169. return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName)
  170. }
  171. lg := log()
  172. err := lg.Init(config)
  173. if err != nil {
  174. fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error())
  175. return err
  176. }
  177. bl.outputs = append(bl.outputs, &nameLogger{name: adapterName, Logger: lg})
  178. return nil
  179. }
  180. // SetLogger provides a given logger adapter into BeeLogger with config string.
  181. // config need to be correct JSON as string: {"interval":360}.
  182. func (bl *BeeLogger) SetLogger(adapterName string, configs ...string) error {
  183. bl.lock.Lock()
  184. defer bl.lock.Unlock()
  185. if !bl.init {
  186. bl.outputs = []*nameLogger{}
  187. bl.init = true
  188. }
  189. return bl.setLogger(adapterName, configs...)
  190. }
  191. // DelLogger remove a logger adapter in BeeLogger.
  192. func (bl *BeeLogger) DelLogger(adapterName string) error {
  193. bl.lock.Lock()
  194. defer bl.lock.Unlock()
  195. outputs := []*nameLogger{}
  196. for _, lg := range bl.outputs {
  197. if lg.name == adapterName {
  198. lg.Destroy()
  199. } else {
  200. outputs = append(outputs, lg)
  201. }
  202. }
  203. if len(outputs) == len(bl.outputs) {
  204. return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName)
  205. }
  206. bl.outputs = outputs
  207. return nil
  208. }
  209. func (bl *BeeLogger) writeToLoggers(when time.Time, msg string, level int) {
  210. for _, l := range bl.outputs {
  211. err := l.WriteMsg(when, msg, level)
  212. if err != nil {
  213. fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err)
  214. }
  215. }
  216. }
  217. func (bl *BeeLogger) Write(p []byte) (n int, err error) {
  218. if len(p) == 0 {
  219. return 0, nil
  220. }
  221. // writeMsg will always add a '\n' character
  222. if p[len(p)-1] == '\n' {
  223. p = p[0 : len(p)-1]
  224. }
  225. // set levelLoggerImpl to ensure all log message will be write out
  226. err = bl.writeMsg(levelLoggerImpl, string(p))
  227. if err == nil {
  228. return len(p), err
  229. }
  230. return 0, err
  231. }
  232. func (bl *BeeLogger) writeMsg(logLevel int, msg string, v ...interface{}) error {
  233. if !bl.init {
  234. bl.lock.Lock()
  235. bl.setLogger(AdapterConsole)
  236. bl.lock.Unlock()
  237. }
  238. if logLevel == levelLoggerImpl {
  239. // set to emergency to ensure all log will be print out correctly
  240. logLevel = LevelEmergency
  241. } else {
  242. msg = levelPrefix[logLevel] + msg
  243. }
  244. if len(v) > 0 {
  245. msg = fmt.Sprintf(msg, v...)
  246. }
  247. when := time.Now()
  248. if bl.enableFuncCallDepth {
  249. _, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth)
  250. if !ok {
  251. file = "???"
  252. line = 0
  253. }
  254. _, filename := path.Split(file)
  255. msg = "[" + filename + ":" + strconv.FormatInt(int64(line), 10) + "] " + msg
  256. }
  257. if bl.asynchronous {
  258. lm := logMsgPool.Get().(*logMsg)
  259. lm.level = logLevel
  260. lm.msg = msg
  261. lm.when = when
  262. bl.msgChan <- lm
  263. } else {
  264. bl.writeToLoggers(when, msg, logLevel)
  265. }
  266. return nil
  267. }
  268. // SetLevel Set log message level.
  269. // If message level (such as LevelDebug) is higher than logger level (such as LevelWarning),
  270. // log providers will not even be sent the message.
  271. func (bl *BeeLogger) SetLevel(l int) {
  272. bl.level = l
  273. }
  274. // SetLogFuncCallDepth set log funcCallDepth
  275. func (bl *BeeLogger) SetLogFuncCallDepth(d int) {
  276. bl.loggerFuncCallDepth = d
  277. }
  278. // GetLogFuncCallDepth return log funcCallDepth for wrapper
  279. func (bl *BeeLogger) GetLogFuncCallDepth() int {
  280. return bl.loggerFuncCallDepth
  281. }
  282. // EnableFuncCallDepth enable log funcCallDepth
  283. func (bl *BeeLogger) EnableFuncCallDepth(b bool) {
  284. bl.enableFuncCallDepth = b
  285. }
  286. // start logger chan reading.
  287. // when chan is not empty, write logs.
  288. func (bl *BeeLogger) startLogger() {
  289. gameOver := false
  290. for {
  291. select {
  292. case bm := <-bl.msgChan:
  293. bl.writeToLoggers(bm.when, bm.msg, bm.level)
  294. logMsgPool.Put(bm)
  295. case sg := <-bl.signalChan:
  296. // Now should only send "flush" or "close" to bl.signalChan
  297. bl.flush()
  298. if sg == "close" {
  299. for _, l := range bl.outputs {
  300. l.Destroy()
  301. }
  302. bl.outputs = nil
  303. gameOver = true
  304. }
  305. bl.wg.Done()
  306. }
  307. if gameOver {
  308. break
  309. }
  310. }
  311. }
  312. // Emergency Log EMERGENCY level message.
  313. func (bl *BeeLogger) Emergency(format string, v ...interface{}) {
  314. if LevelEmergency > bl.level {
  315. return
  316. }
  317. bl.writeMsg(LevelEmergency, format, v...)
  318. }
  319. // Alert Log ALERT level message.
  320. func (bl *BeeLogger) Alert(format string, v ...interface{}) {
  321. if LevelAlert > bl.level {
  322. return
  323. }
  324. bl.writeMsg(LevelAlert, format, v...)
  325. }
  326. // Critical Log CRITICAL level message.
  327. func (bl *BeeLogger) Critical(format string, v ...interface{}) {
  328. if LevelCritical > bl.level {
  329. return
  330. }
  331. bl.writeMsg(LevelCritical, format, v...)
  332. }
  333. // Error Log ERROR level message.
  334. func (bl *BeeLogger) Error(format string, v ...interface{}) {
  335. if LevelError > bl.level {
  336. return
  337. }
  338. bl.writeMsg(LevelError, format, v...)
  339. }
  340. // Warning Log WARNING level message.
  341. func (bl *BeeLogger) Warning(format string, v ...interface{}) {
  342. bl.Warn(format, v...)
  343. }
  344. // Notice Log NOTICE level message.
  345. func (bl *BeeLogger) Notice(format string, v ...interface{}) {
  346. if LevelNotice > bl.level {
  347. return
  348. }
  349. bl.writeMsg(LevelNotice, format, v...)
  350. }
  351. // Informational Log INFORMATIONAL level message.
  352. func (bl *BeeLogger) Informational(format string, v ...interface{}) {
  353. bl.Info(format, v...)
  354. }
  355. // Debug Log DEBUG level message.
  356. func (bl *BeeLogger) Debug(format string, v ...interface{}) {
  357. if LevelDebug > bl.level {
  358. return
  359. }
  360. bl.writeMsg(LevelDebug, format, v...)
  361. }
  362. // Warn Log WARN level message.
  363. // compatibility alias for Warning()
  364. func (bl *BeeLogger) Warn(format string, v ...interface{}) {
  365. if LevelWarn > bl.level {
  366. return
  367. }
  368. bl.writeMsg(LevelWarn, format, v...)
  369. }
  370. // Info Log INFO level message.
  371. // compatibility alias for Informational()
  372. func (bl *BeeLogger) Info(format string, v ...interface{}) {
  373. if LevelInfo > bl.level {
  374. return
  375. }
  376. bl.writeMsg(LevelInfo, format, v...)
  377. }
  378. // Trace Log TRACE level message.
  379. // compatibility alias for Debug()
  380. func (bl *BeeLogger) Trace(format string, v ...interface{}) {
  381. bl.Debug(format, v...)
  382. }
  383. // Flush flush all chan data.
  384. func (bl *BeeLogger) Flush() {
  385. if bl.asynchronous {
  386. bl.signalChan <- "flush"
  387. bl.wg.Wait()
  388. bl.wg.Add(1)
  389. return
  390. }
  391. bl.flush()
  392. }
  393. // Close close logger, flush all chan data and destroy all adapters in BeeLogger.
  394. func (bl *BeeLogger) Close() {
  395. if bl.asynchronous {
  396. bl.signalChan <- "close"
  397. bl.wg.Wait()
  398. close(bl.msgChan)
  399. } else {
  400. bl.flush()
  401. for _, l := range bl.outputs {
  402. l.Destroy()
  403. }
  404. bl.outputs = nil
  405. }
  406. close(bl.signalChan)
  407. }
  408. // Reset close all outputs, and set bl.outputs to nil
  409. func (bl *BeeLogger) Reset() {
  410. bl.Flush()
  411. for _, l := range bl.outputs {
  412. l.Destroy()
  413. }
  414. bl.outputs = nil
  415. }
  416. func (bl *BeeLogger) flush() {
  417. if bl.asynchronous {
  418. for {
  419. if len(bl.msgChan) > 0 {
  420. bm := <-bl.msgChan
  421. bl.writeToLoggers(bm.when, bm.msg, bm.level)
  422. logMsgPool.Put(bm)
  423. continue
  424. }
  425. break
  426. }
  427. }
  428. for _, l := range bl.outputs {
  429. l.Flush()
  430. }
  431. }
  432. // beeLogger references the used application logger.
  433. var beeLogger *BeeLogger = NewLogger()
  434. // GetLogger returns the default BeeLogger
  435. func GetBeeLogger() *BeeLogger {
  436. return beeLogger
  437. }
  438. var beeLoggerMap = struct {
  439. sync.RWMutex
  440. logs map[string]*log.Logger
  441. }{
  442. logs: map[string]*log.Logger{},
  443. }
  444. // GetLogger returns the default BeeLogger
  445. func GetLogger(prefixes ...string) *log.Logger {
  446. prefix := append(prefixes, "")[0]
  447. if prefix != "" {
  448. prefix = fmt.Sprintf(`[%s] `, strings.ToUpper(prefix))
  449. }
  450. beeLoggerMap.RLock()
  451. l, ok := beeLoggerMap.logs[prefix]
  452. if ok {
  453. beeLoggerMap.RUnlock()
  454. return l
  455. }
  456. beeLoggerMap.RUnlock()
  457. beeLoggerMap.Lock()
  458. defer beeLoggerMap.Unlock()
  459. l, ok = beeLoggerMap.logs[prefix]
  460. if !ok {
  461. l = log.New(beeLogger, prefix, 0)
  462. beeLoggerMap.logs[prefix] = l
  463. }
  464. return l
  465. }
  466. // Reset will remove all the adapter
  467. func Reset() {
  468. beeLogger.Reset()
  469. }
  470. func Async(msgLen ...int64) *BeeLogger {
  471. return beeLogger.Async(msgLen...)
  472. }
  473. // SetLevel sets the global log level used by the simple logger.
  474. func SetLevel(l int) {
  475. beeLogger.SetLevel(l)
  476. }
  477. // EnableFuncCallDepth enable log funcCallDepth
  478. func EnableFuncCallDepth(b bool) {
  479. beeLogger.enableFuncCallDepth = b
  480. }
  481. // SetLogFuncCall set the CallDepth, default is 3
  482. func SetLogFuncCall(b bool) {
  483. beeLogger.EnableFuncCallDepth(b)
  484. beeLogger.SetLogFuncCallDepth(3)
  485. }
  486. // SetLogFuncCallDepth set log funcCallDepth
  487. func SetLogFuncCallDepth(d int) {
  488. beeLogger.loggerFuncCallDepth = d
  489. }
  490. // SetLogger sets a new logger.
  491. func SetLogger(adapter string, config ...string) error {
  492. err := beeLogger.SetLogger(adapter, config...)
  493. if err != nil {
  494. return err
  495. }
  496. return nil
  497. }
  498. // Emergency logs a message at emergency level.
  499. func Emergency(f interface{}, v ...interface{}) {
  500. beeLogger.Emergency(formatLog(f, v...))
  501. }
  502. // Alert logs a message at alert level.
  503. func Alert(f interface{}, v ...interface{}) {
  504. beeLogger.Alert(formatLog(f, v...))
  505. }
  506. // Critical logs a message at critical level.
  507. func Critical(f interface{}, v ...interface{}) {
  508. beeLogger.Critical(formatLog(f, v...))
  509. }
  510. // Error logs a message at error level.
  511. func Error(f interface{}, v ...interface{}) {
  512. beeLogger.Error(formatLog(f, v...))
  513. }
  514. // Warning logs a message at warning level.
  515. func Warning(f interface{}, v ...interface{}) {
  516. beeLogger.Warn(formatLog(f, v...))
  517. }
  518. // Warn compatibility alias for Warning()
  519. func Warn(f interface{}, v ...interface{}) {
  520. beeLogger.Warn(formatLog(f, v...))
  521. }
  522. // Notice logs a message at notice level.
  523. func Notice(f interface{}, v ...interface{}) {
  524. beeLogger.Notice(formatLog(f, v...))
  525. }
  526. // Informational logs a message at info level.
  527. func Informational(f interface{}, v ...interface{}) {
  528. beeLogger.Info(formatLog(f, v...))
  529. }
  530. // Info compatibility alias for Warning()
  531. func Info(f interface{}, v ...interface{}) {
  532. beeLogger.Info(formatLog(f, v...))
  533. }
  534. // Debug logs a message at debug level.
  535. func Debug(f interface{}, v ...interface{}) {
  536. beeLogger.Debug(formatLog(f, v...))
  537. }
  538. // Trace logs a message at trace level.
  539. // compatibility alias for Warning()
  540. func Trace(f interface{}, v ...interface{}) {
  541. beeLogger.Trace(formatLog(f, v...))
  542. }
  543. func formatLog(f interface{}, v ...interface{}) string {
  544. var msg string
  545. switch f.(type) {
  546. case string:
  547. msg = f.(string)
  548. if len(v) == 0 {
  549. return msg
  550. }
  551. if strings.Contains(msg, "%") && !strings.Contains(msg, "%%") {
  552. //format string
  553. } else {
  554. //do not contain format char
  555. msg += strings.Repeat(" %v", len(v))
  556. }
  557. default:
  558. msg = fmt.Sprint(f)
  559. if len(v) == 0 {
  560. return msg
  561. }
  562. msg += strings.Repeat(" %v", len(v))
  563. }
  564. return fmt.Sprintf(msg, v...)
  565. }