高热共公日志库
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.

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