高热共公日志库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

666 lines
15 KiB

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