log.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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. // Usage:
  15. //
  16. // import "github.com/astaxie/beego/logs"
  17. //
  18. // log := NewLogger(10000)
  19. // log.SetLogger("console", "")
  20. //
  21. // > the first params stand for how many channel
  22. //
  23. // Use it like this:
  24. //
  25. // log.Trace("trace")
  26. // log.Info("info")
  27. // log.Warn("warning")
  28. // log.Debug("debug")
  29. // log.Critical("critical")
  30. //
  31. // more docs http://beego.me/docs/module/logs.md
  32. package logs
  33. import (
  34. "fmt"
  35. "path"
  36. "runtime"
  37. "sync"
  38. )
  39. // RFC5424 log message levels.
  40. const (
  41. LevelEmergency = iota
  42. LevelAlert
  43. LevelCritical
  44. LevelError
  45. LevelWarning
  46. LevelNotice
  47. LevelInformational
  48. LevelDebug
  49. )
  50. // Legacy loglevel constants to ensure backwards compatibility.
  51. //
  52. // Deprecated: will be removed in 1.5.0.
  53. const (
  54. LevelInfo = LevelInformational
  55. LevelTrace = LevelDebug
  56. LevelWarn = LevelWarning
  57. )
  58. type loggerType func() LoggerInterface
  59. // LoggerInterface defines the behavior of a log provider.
  60. type LoggerInterface interface {
  61. Init(config string) error
  62. WriteMsg(msg string, level int) error
  63. Destroy()
  64. Flush()
  65. }
  66. var adapters = make(map[string]loggerType)
  67. // Register makes a log provide available by the provided name.
  68. // If Register is called twice with the same name or if driver is nil,
  69. // it panics.
  70. func Register(name string, log loggerType) {
  71. if log == nil {
  72. panic("logs: Register provide is nil")
  73. }
  74. if _, dup := adapters[name]; dup {
  75. panic("logs: Register called twice for provider " + name)
  76. }
  77. adapters[name] = log
  78. }
  79. // BeeLogger is default logger in beego application.
  80. // it can contain several providers and log message into all providers.
  81. type BeeLogger struct {
  82. lock sync.Mutex
  83. level int
  84. enableFuncCallDepth bool
  85. loggerFuncCallDepth int
  86. asynchronous bool
  87. msg chan *logMsg
  88. outputs map[string]LoggerInterface
  89. }
  90. type logMsg struct {
  91. level int
  92. msg string
  93. }
  94. // NewLogger returns a new BeeLogger.
  95. // channellen means the number of messages in chan.
  96. // if the buffering chan is full, logger adapters write to file or other way.
  97. func NewLogger(channellen int64) *BeeLogger {
  98. bl := new(BeeLogger)
  99. bl.level = LevelDebug
  100. bl.loggerFuncCallDepth = 2
  101. bl.msg = make(chan *logMsg, channellen)
  102. bl.outputs = make(map[string]LoggerInterface)
  103. return bl
  104. }
  105. func (bl *BeeLogger) Async() *BeeLogger {
  106. bl.asynchronous = true
  107. go bl.startLogger()
  108. return bl
  109. }
  110. // SetLogger provides a given logger adapter into BeeLogger with config string.
  111. // config need to be correct JSON as string: {"interval":360}.
  112. func (bl *BeeLogger) SetLogger(adaptername string, config string) error {
  113. bl.lock.Lock()
  114. defer bl.lock.Unlock()
  115. if log, ok := adapters[adaptername]; ok {
  116. lg := log()
  117. err := lg.Init(config)
  118. bl.outputs[adaptername] = lg
  119. if err != nil {
  120. fmt.Println("logs.BeeLogger.SetLogger: " + err.Error())
  121. return err
  122. }
  123. } else {
  124. return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adaptername)
  125. }
  126. return nil
  127. }
  128. // remove a logger adapter in BeeLogger.
  129. func (bl *BeeLogger) DelLogger(adaptername string) error {
  130. bl.lock.Lock()
  131. defer bl.lock.Unlock()
  132. if lg, ok := bl.outputs[adaptername]; ok {
  133. lg.Destroy()
  134. delete(bl.outputs, adaptername)
  135. return nil
  136. } else {
  137. return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adaptername)
  138. }
  139. }
  140. func (bl *BeeLogger) writerMsg(loglevel int, msg string) error {
  141. lm := new(logMsg)
  142. lm.level = loglevel
  143. if bl.enableFuncCallDepth {
  144. _, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth)
  145. if !ok {
  146. file = "???"
  147. line = 0
  148. }
  149. _, filename := path.Split(file)
  150. lm.msg = fmt.Sprintf("[%s:%d] %s", filename, line, msg)
  151. } else {
  152. lm.msg = msg
  153. }
  154. if bl.asynchronous {
  155. bl.msg <- lm
  156. } else {
  157. for name, l := range bl.outputs {
  158. err := l.WriteMsg(lm.msg, lm.level)
  159. if err != nil {
  160. fmt.Println("unable to WriteMsg to adapter:", name, err)
  161. return err
  162. }
  163. }
  164. }
  165. return nil
  166. }
  167. // Set log message level.
  168. //
  169. // If message level (such as LevelDebug) is higher than logger level (such as LevelWarning),
  170. // log providers will not even be sent the message.
  171. func (bl *BeeLogger) SetLevel(l int) {
  172. bl.level = l
  173. }
  174. // set log funcCallDepth
  175. func (bl *BeeLogger) SetLogFuncCallDepth(d int) {
  176. bl.loggerFuncCallDepth = d
  177. }
  178. // get log funcCallDepth for wrapper
  179. func (bl *BeeLogger) GetLogFuncCallDepth() int {
  180. return bl.loggerFuncCallDepth
  181. }
  182. // enable log funcCallDepth
  183. func (bl *BeeLogger) EnableFuncCallDepth(b bool) {
  184. bl.enableFuncCallDepth = b
  185. }
  186. // start logger chan reading.
  187. // when chan is not empty, write logs.
  188. func (bl *BeeLogger) startLogger() {
  189. for {
  190. select {
  191. case bm := <-bl.msg:
  192. for _, l := range bl.outputs {
  193. err := l.WriteMsg(bm.msg, bm.level)
  194. if err != nil {
  195. fmt.Println("ERROR, unable to WriteMsg:", err)
  196. }
  197. }
  198. }
  199. }
  200. }
  201. // Log EMERGENCY level message.
  202. func (bl *BeeLogger) Emergency(format string, v ...interface{}) {
  203. if LevelEmergency > bl.level {
  204. return
  205. }
  206. msg := fmt.Sprintf("[M] "+format, v...)
  207. bl.writerMsg(LevelEmergency, msg)
  208. }
  209. // Log ALERT level message.
  210. func (bl *BeeLogger) Alert(format string, v ...interface{}) {
  211. if LevelAlert > bl.level {
  212. return
  213. }
  214. msg := fmt.Sprintf("[A] "+format, v...)
  215. bl.writerMsg(LevelAlert, msg)
  216. }
  217. // Log CRITICAL level message.
  218. func (bl *BeeLogger) Critical(format string, v ...interface{}) {
  219. if LevelCritical > bl.level {
  220. return
  221. }
  222. msg := fmt.Sprintf("[C] "+format, v...)
  223. bl.writerMsg(LevelCritical, msg)
  224. }
  225. // Log ERROR level message.
  226. func (bl *BeeLogger) Error(format string, v ...interface{}) {
  227. if LevelError > bl.level {
  228. return
  229. }
  230. msg := fmt.Sprintf("[E] "+format, v...)
  231. bl.writerMsg(LevelError, msg)
  232. }
  233. // Log WARNING level message.
  234. func (bl *BeeLogger) Warning(format string, v ...interface{}) {
  235. if LevelWarning > bl.level {
  236. return
  237. }
  238. msg := fmt.Sprintf("[W] "+format, v...)
  239. bl.writerMsg(LevelWarning, msg)
  240. }
  241. // Log NOTICE level message.
  242. func (bl *BeeLogger) Notice(format string, v ...interface{}) {
  243. if LevelNotice > bl.level {
  244. return
  245. }
  246. msg := fmt.Sprintf("[N] "+format, v...)
  247. bl.writerMsg(LevelNotice, msg)
  248. }
  249. // Log INFORMATIONAL level message.
  250. func (bl *BeeLogger) Informational(format string, v ...interface{}) {
  251. if LevelInformational > bl.level {
  252. return
  253. }
  254. msg := fmt.Sprintf("[I] "+format, v...)
  255. bl.writerMsg(LevelInformational, msg)
  256. }
  257. // Log DEBUG level message.
  258. func (bl *BeeLogger) Debug(format string, v ...interface{}) {
  259. if LevelDebug > bl.level {
  260. return
  261. }
  262. msg := fmt.Sprintf("[D] "+format, v...)
  263. bl.writerMsg(LevelDebug, msg)
  264. }
  265. // Log WARN level message.
  266. // compatibility alias for Warning()
  267. func (bl *BeeLogger) Warn(format string, v ...interface{}) {
  268. if LevelWarning > bl.level {
  269. return
  270. }
  271. msg := fmt.Sprintf("[W] "+format, v...)
  272. bl.writerMsg(LevelWarning, msg)
  273. }
  274. // Log INFO level message.
  275. // compatibility alias for Informational()
  276. func (bl *BeeLogger) Info(format string, v ...interface{}) {
  277. if LevelInformational > bl.level {
  278. return
  279. }
  280. msg := fmt.Sprintf("[I] "+format, v...)
  281. bl.writerMsg(LevelInformational, msg)
  282. }
  283. // Log TRACE level message.
  284. // compatibility alias for Debug()
  285. func (bl *BeeLogger) Trace(format string, v ...interface{}) {
  286. if LevelDebug > bl.level {
  287. return
  288. }
  289. msg := fmt.Sprintf("[D] "+format, v...)
  290. bl.writerMsg(LevelDebug, msg)
  291. }
  292. // flush all chan data.
  293. func (bl *BeeLogger) Flush() {
  294. for _, l := range bl.outputs {
  295. l.Flush()
  296. }
  297. }
  298. // close logger, flush all chan data and destroy all adapters in BeeLogger.
  299. func (bl *BeeLogger) Close() {
  300. for {
  301. if len(bl.msg) > 0 {
  302. bm := <-bl.msg
  303. for _, l := range bl.outputs {
  304. err := l.WriteMsg(bm.msg, bm.level)
  305. if err != nil {
  306. fmt.Println("ERROR, unable to WriteMsg (while closing logger):", err)
  307. }
  308. }
  309. continue
  310. }
  311. break
  312. }
  313. for _, l := range bl.outputs {
  314. l.Flush()
  315. l.Destroy()
  316. }
  317. }