log.go 15 KB

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