log.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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. "os"
  37. "path"
  38. "runtime"
  39. "strconv"
  40. "sync"
  41. "time"
  42. )
  43. // RFC5424 log message levels.
  44. const (
  45. LevelEmergency = iota
  46. LevelAlert
  47. LevelCritical
  48. LevelError
  49. LevelWarning
  50. LevelNotice
  51. LevelInformational
  52. LevelDebug
  53. )
  54. // Legacy loglevel constants to ensure backwards compatibility.
  55. //
  56. // Deprecated: will be removed in 1.5.0.
  57. const (
  58. LevelInfo = LevelInformational
  59. LevelTrace = LevelDebug
  60. LevelWarn = LevelWarning
  61. )
  62. type loggerType func() Logger
  63. // Logger defines the behavior of a log provider.
  64. type Logger interface {
  65. Init(config string) error
  66. WriteMsg(when time.Time, msg string, level int) error
  67. Destroy()
  68. Flush()
  69. }
  70. var adapters = make(map[string]loggerType)
  71. // Register makes a log provide available by the provided name.
  72. // If Register is called twice with the same name or if driver is nil,
  73. // it panics.
  74. func Register(name string, log loggerType) {
  75. if log == nil {
  76. panic("logs: Register provide is nil")
  77. }
  78. if _, dup := adapters[name]; dup {
  79. panic("logs: Register called twice for provider " + name)
  80. }
  81. adapters[name] = log
  82. }
  83. // BeeLogger is default logger in beego application.
  84. // it can contain several providers and log message into all providers.
  85. type BeeLogger struct {
  86. lock sync.Mutex
  87. level int
  88. enableFuncCallDepth bool
  89. loggerFuncCallDepth int
  90. asynchronous bool
  91. msgChan chan *logMsg
  92. signalChan chan string
  93. wg sync.WaitGroup
  94. outputs []*nameLogger
  95. }
  96. type nameLogger struct {
  97. Logger
  98. name string
  99. }
  100. type logMsg struct {
  101. level int
  102. msg string
  103. when time.Time
  104. }
  105. var logMsgPool *sync.Pool
  106. // NewLogger returns a new BeeLogger.
  107. // channelLen means the number of messages in chan(used where asynchronous is true).
  108. // if the buffering chan is full, logger adapters write to file or other way.
  109. func NewLogger(channelLen int64) *BeeLogger {
  110. bl := new(BeeLogger)
  111. bl.level = LevelDebug
  112. bl.loggerFuncCallDepth = 2
  113. bl.msgChan = make(chan *logMsg, channelLen)
  114. bl.signalChan = make(chan string, 1)
  115. return bl
  116. }
  117. // Async set the log to asynchronous and start the goroutine
  118. func (bl *BeeLogger) Async() *BeeLogger {
  119. bl.asynchronous = true
  120. logMsgPool = &sync.Pool{
  121. New: func() interface{} {
  122. return &logMsg{}
  123. },
  124. }
  125. bl.wg.Add(1)
  126. go bl.startLogger()
  127. return bl
  128. }
  129. // SetLogger provides a given logger adapter into BeeLogger with config string.
  130. // config need to be correct JSON as string: {"interval":360}.
  131. func (bl *BeeLogger) SetLogger(adapterName string, config string) error {
  132. bl.lock.Lock()
  133. defer bl.lock.Unlock()
  134. for _, l := range bl.outputs {
  135. if l.name == adapterName {
  136. return fmt.Errorf("logs: duplicate adaptername %q (you have set this logger before)", adapterName)
  137. }
  138. }
  139. log, ok := adapters[adapterName]
  140. if !ok {
  141. return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName)
  142. }
  143. lg := log()
  144. err := lg.Init(config)
  145. if err != nil {
  146. fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error())
  147. return err
  148. }
  149. bl.outputs = append(bl.outputs, &nameLogger{name: adapterName, Logger: lg})
  150. return nil
  151. }
  152. // DelLogger remove a logger adapter in BeeLogger.
  153. func (bl *BeeLogger) DelLogger(adapterName string) error {
  154. bl.lock.Lock()
  155. defer bl.lock.Unlock()
  156. outputs := []*nameLogger{}
  157. for _, lg := range bl.outputs {
  158. if lg.name == adapterName {
  159. lg.Destroy()
  160. } else {
  161. outputs = append(outputs, lg)
  162. }
  163. }
  164. if len(outputs) == len(bl.outputs) {
  165. return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName)
  166. }
  167. bl.outputs = outputs
  168. return nil
  169. }
  170. func (bl *BeeLogger) writeToLoggers(when time.Time, msg string, level int) {
  171. for _, l := range bl.outputs {
  172. err := l.WriteMsg(when, msg, level)
  173. if err != nil {
  174. fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err)
  175. }
  176. }
  177. }
  178. func (bl *BeeLogger) writeMsg(logLevel int, msg string) error {
  179. when := time.Now()
  180. if bl.enableFuncCallDepth {
  181. _, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth)
  182. if !ok {
  183. file = "???"
  184. line = 0
  185. }
  186. _, filename := path.Split(file)
  187. msg = "[" + filename + ":" + strconv.FormatInt(int64(line), 10) + "]" + msg
  188. }
  189. if bl.asynchronous {
  190. lm := logMsgPool.Get().(*logMsg)
  191. lm.level = logLevel
  192. lm.msg = msg
  193. lm.when = when
  194. bl.msgChan <- lm
  195. } else {
  196. bl.writeToLoggers(when, msg, logLevel)
  197. }
  198. return nil
  199. }
  200. // SetLevel Set log message level.
  201. // If message level (such as LevelDebug) is higher than logger level (such as LevelWarning),
  202. // log providers will not even be sent the message.
  203. func (bl *BeeLogger) SetLevel(l int) {
  204. bl.level = l
  205. }
  206. // SetLogFuncCallDepth set log funcCallDepth
  207. func (bl *BeeLogger) SetLogFuncCallDepth(d int) {
  208. bl.loggerFuncCallDepth = d
  209. }
  210. // GetLogFuncCallDepth return log funcCallDepth for wrapper
  211. func (bl *BeeLogger) GetLogFuncCallDepth() int {
  212. return bl.loggerFuncCallDepth
  213. }
  214. // EnableFuncCallDepth enable log funcCallDepth
  215. func (bl *BeeLogger) EnableFuncCallDepth(b bool) {
  216. bl.enableFuncCallDepth = b
  217. }
  218. // start logger chan reading.
  219. // when chan is not empty, write logs.
  220. func (bl *BeeLogger) startLogger() {
  221. gameOver := false
  222. for {
  223. select {
  224. case bm := <-bl.msgChan:
  225. bl.writeToLoggers(bm.when, bm.msg, bm.level)
  226. logMsgPool.Put(bm)
  227. case sg := <-bl.signalChan:
  228. // Now should only send "flush" or "close" to bl.signalChan
  229. bl.flush()
  230. if sg == "close" {
  231. for _, l := range bl.outputs {
  232. l.Destroy()
  233. }
  234. bl.outputs = nil
  235. gameOver = true
  236. }
  237. bl.wg.Done()
  238. }
  239. if gameOver {
  240. break
  241. }
  242. }
  243. }
  244. // Emergency Log EMERGENCY level message.
  245. func (bl *BeeLogger) Emergency(format string, v ...interface{}) {
  246. if LevelEmergency > bl.level {
  247. return
  248. }
  249. msg := fmt.Sprintf("[M] "+format, v...)
  250. bl.writeMsg(LevelEmergency, msg)
  251. }
  252. // Alert Log ALERT level message.
  253. func (bl *BeeLogger) Alert(format string, v ...interface{}) {
  254. if LevelAlert > bl.level {
  255. return
  256. }
  257. msg := fmt.Sprintf("[A] "+format, v...)
  258. bl.writeMsg(LevelAlert, msg)
  259. }
  260. // Critical Log CRITICAL level message.
  261. func (bl *BeeLogger) Critical(format string, v ...interface{}) {
  262. if LevelCritical > bl.level {
  263. return
  264. }
  265. msg := fmt.Sprintf("[C] "+format, v...)
  266. bl.writeMsg(LevelCritical, msg)
  267. }
  268. // Error Log ERROR level message.
  269. func (bl *BeeLogger) Error(format string, v ...interface{}) {
  270. if LevelError > bl.level {
  271. return
  272. }
  273. msg := fmt.Sprintf("[E] "+format, v...)
  274. bl.writeMsg(LevelError, msg)
  275. }
  276. // Warning Log WARNING level message.
  277. func (bl *BeeLogger) Warning(format string, v ...interface{}) {
  278. if LevelWarning > bl.level {
  279. return
  280. }
  281. msg := fmt.Sprintf("[W] "+format, v...)
  282. bl.writeMsg(LevelWarning, msg)
  283. }
  284. // Notice Log NOTICE level message.
  285. func (bl *BeeLogger) Notice(format string, v ...interface{}) {
  286. if LevelNotice > bl.level {
  287. return
  288. }
  289. msg := fmt.Sprintf("[N] "+format, v...)
  290. bl.writeMsg(LevelNotice, msg)
  291. }
  292. // Informational Log INFORMATIONAL level message.
  293. func (bl *BeeLogger) Informational(format string, v ...interface{}) {
  294. if LevelInformational > bl.level {
  295. return
  296. }
  297. msg := fmt.Sprintf("[I] "+format, v...)
  298. bl.writeMsg(LevelInformational, msg)
  299. }
  300. // Debug Log DEBUG level message.
  301. func (bl *BeeLogger) Debug(format string, v ...interface{}) {
  302. if LevelDebug > bl.level {
  303. return
  304. }
  305. msg := fmt.Sprintf("[D] "+format, v...)
  306. bl.writeMsg(LevelDebug, msg)
  307. }
  308. // Warn Log WARN level message.
  309. // compatibility alias for Warning()
  310. func (bl *BeeLogger) Warn(format string, v ...interface{}) {
  311. if LevelWarning > bl.level {
  312. return
  313. }
  314. msg := fmt.Sprintf("[W] "+format, v...)
  315. bl.writeMsg(LevelWarning, msg)
  316. }
  317. // Info Log INFO level message.
  318. // compatibility alias for Informational()
  319. func (bl *BeeLogger) Info(format string, v ...interface{}) {
  320. if LevelInformational > bl.level {
  321. return
  322. }
  323. msg := fmt.Sprintf("[I] "+format, v...)
  324. bl.writeMsg(LevelInformational, msg)
  325. }
  326. // Trace Log TRACE level message.
  327. // compatibility alias for Debug()
  328. func (bl *BeeLogger) Trace(format string, v ...interface{}) {
  329. if LevelDebug > bl.level {
  330. return
  331. }
  332. msg := fmt.Sprintf("[D] "+format, v...)
  333. bl.writeMsg(LevelDebug, msg)
  334. }
  335. // Flush flush all chan data.
  336. func (bl *BeeLogger) Flush() {
  337. if bl.asynchronous {
  338. bl.signalChan <- "flush"
  339. bl.wg.Wait()
  340. bl.wg.Add(1)
  341. return
  342. }
  343. bl.flush()
  344. }
  345. // Close close logger, flush all chan data and destroy all adapters in BeeLogger.
  346. func (bl *BeeLogger) Close() {
  347. if bl.asynchronous {
  348. bl.signalChan <- "close"
  349. bl.wg.Wait()
  350. } else {
  351. bl.flush()
  352. for _, l := range bl.outputs {
  353. l.Destroy()
  354. }
  355. bl.outputs = nil
  356. }
  357. close(bl.msgChan)
  358. close(bl.signalChan)
  359. }
  360. // Reset close all outputs, and set bl.outputs to nil
  361. func (bl *BeeLogger) Reset() {
  362. bl.Flush()
  363. for _, l := range bl.outputs {
  364. l.Destroy()
  365. }
  366. bl.outputs = nil
  367. }
  368. func (bl *BeeLogger) flush() {
  369. for {
  370. if len(bl.msgChan) > 0 {
  371. bm := <-bl.msgChan
  372. bl.writeToLoggers(bm.when, bm.msg, bm.level)
  373. logMsgPool.Put(bm)
  374. continue
  375. }
  376. break
  377. }
  378. for _, l := range bl.outputs {
  379. l.Flush()
  380. }
  381. }