You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

log.go 7.4 kB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package log
  5. import (
  6. "fmt"
  7. "os"
  8. "path"
  9. "path/filepath"
  10. "runtime"
  11. "strings"
  12. "sync"
  13. )
  14. var (
  15. loggers []*Logger
  16. // GitLogger logger for git
  17. GitLogger *Logger
  18. )
  19. // NewLogger create a logger
  20. func NewLogger(bufLen int64, mode, config string) {
  21. logger := newLogger(bufLen)
  22. isExist := false
  23. for i, l := range loggers {
  24. if l.adapter == mode {
  25. isExist = true
  26. loggers[i] = logger
  27. }
  28. }
  29. if !isExist {
  30. loggers = append(loggers, logger)
  31. }
  32. if err := logger.SetLogger(mode, config); err != nil {
  33. Fatal(2, "Fail to set logger (%s): %v", mode, err)
  34. }
  35. }
  36. // NewGitLogger create a logger for git
  37. // FIXME: use same log level as other loggers.
  38. func NewGitLogger(logPath string) {
  39. os.MkdirAll(path.Dir(logPath), os.ModePerm)
  40. GitLogger = newLogger(0)
  41. GitLogger.SetLogger("file", fmt.Sprintf(`{"level":0,"filename":"%s","rotate":false}`, logPath))
  42. }
  43. // Trace records trace log
  44. func Trace(format string, v ...interface{}) {
  45. for _, logger := range loggers {
  46. logger.Trace(format, v...)
  47. }
  48. }
  49. // Debug records debug log
  50. func Debug(format string, v ...interface{}) {
  51. for _, logger := range loggers {
  52. logger.Debug(format, v...)
  53. }
  54. }
  55. // Info records info log
  56. func Info(format string, v ...interface{}) {
  57. for _, logger := range loggers {
  58. logger.Info(format, v...)
  59. }
  60. }
  61. // Warn records warnning log
  62. func Warn(format string, v ...interface{}) {
  63. for _, logger := range loggers {
  64. logger.Warn(format, v...)
  65. }
  66. }
  67. // Error records error log
  68. func Error(skip int, format string, v ...interface{}) {
  69. for _, logger := range loggers {
  70. logger.Error(skip, format, v...)
  71. }
  72. }
  73. // Critical records critical log
  74. func Critical(skip int, format string, v ...interface{}) {
  75. for _, logger := range loggers {
  76. logger.Critical(skip, format, v...)
  77. }
  78. }
  79. // Fatal records error log and exit process
  80. func Fatal(skip int, format string, v ...interface{}) {
  81. Error(skip, format, v...)
  82. for _, l := range loggers {
  83. l.Close()
  84. }
  85. os.Exit(1)
  86. }
  87. // Close closes all the loggers
  88. func Close() {
  89. for _, l := range loggers {
  90. l.Close()
  91. }
  92. }
  93. // .___ __ _____
  94. // | | _____/ |_ ____________/ ____\____ ____ ____
  95. // | |/ \ __\/ __ \_ __ \ __\\__ \ _/ ___\/ __ \
  96. // | | | \ | \ ___/| | \/| | / __ \\ \__\ ___/
  97. // |___|___| /__| \___ >__| |__| (____ /\___ >___ >
  98. // \/ \/ \/ \/ \/
  99. // LogLevel level type for log
  100. //type LogLevel int
  101. // log levels
  102. const (
  103. TRACE = iota
  104. DEBUG
  105. INFO
  106. WARN
  107. ERROR
  108. CRITICAL
  109. FATAL
  110. )
  111. // LoggerInterface represents behaviors of a logger provider.
  112. type LoggerInterface interface {
  113. Init(config string) error
  114. WriteMsg(msg string, skip, level int) error
  115. Destroy()
  116. Flush()
  117. }
  118. type loggerType func() LoggerInterface
  119. var adapters = make(map[string]loggerType)
  120. // Register registers given logger provider to adapters.
  121. func Register(name string, log loggerType) {
  122. if log == nil {
  123. panic("log: register provider is nil")
  124. }
  125. if _, dup := adapters[name]; dup {
  126. panic("log: register called twice for provider \"" + name + "\"")
  127. }
  128. adapters[name] = log
  129. }
  130. type logMsg struct {
  131. skip, level int
  132. msg string
  133. }
  134. // Logger is default logger in beego application.
  135. // it can contain several providers and log message into all providers.
  136. type Logger struct {
  137. adapter string
  138. lock sync.Mutex
  139. level int
  140. msg chan *logMsg
  141. outputs map[string]LoggerInterface
  142. quit chan bool
  143. }
  144. // newLogger initializes and returns a new logger.
  145. func newLogger(buffer int64) *Logger {
  146. l := &Logger{
  147. msg: make(chan *logMsg, buffer),
  148. outputs: make(map[string]LoggerInterface),
  149. quit: make(chan bool),
  150. }
  151. go l.StartLogger()
  152. return l
  153. }
  154. // SetLogger sets new logger instance with given logger adapter and config.
  155. func (l *Logger) SetLogger(adapter string, config string) error {
  156. l.lock.Lock()
  157. defer l.lock.Unlock()
  158. if log, ok := adapters[adapter]; ok {
  159. lg := log()
  160. if err := lg.Init(config); err != nil {
  161. return err
  162. }
  163. l.outputs[adapter] = lg
  164. l.adapter = adapter
  165. } else {
  166. panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
  167. }
  168. return nil
  169. }
  170. // DelLogger removes a logger adapter instance.
  171. func (l *Logger) DelLogger(adapter string) error {
  172. l.lock.Lock()
  173. defer l.lock.Unlock()
  174. if lg, ok := l.outputs[adapter]; ok {
  175. lg.Destroy()
  176. delete(l.outputs, adapter)
  177. } else {
  178. panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
  179. }
  180. return nil
  181. }
  182. func (l *Logger) writerMsg(skip, level int, msg string) error {
  183. if l.level > level {
  184. return nil
  185. }
  186. lm := &logMsg{
  187. skip: skip,
  188. level: level,
  189. }
  190. // Only error information needs locate position for debugging.
  191. if lm.level >= ERROR {
  192. pc, file, line, ok := runtime.Caller(skip)
  193. if ok {
  194. // Get caller function name.
  195. fn := runtime.FuncForPC(pc)
  196. var fnName string
  197. if fn == nil {
  198. fnName = "?()"
  199. } else {
  200. fnName = strings.TrimLeft(filepath.Ext(fn.Name()), ".") + "()"
  201. }
  202. fileName := file
  203. if len(fileName) > 20 {
  204. fileName = "..." + fileName[len(fileName)-20:]
  205. }
  206. lm.msg = fmt.Sprintf("[%s:%d %s] %s", fileName, line, fnName, msg)
  207. } else {
  208. lm.msg = msg
  209. }
  210. } else {
  211. lm.msg = msg
  212. }
  213. l.msg <- lm
  214. return nil
  215. }
  216. // StartLogger starts logger chan reading.
  217. func (l *Logger) StartLogger() {
  218. for {
  219. select {
  220. case bm := <-l.msg:
  221. for _, l := range l.outputs {
  222. if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
  223. fmt.Println("ERROR, unable to WriteMsg:", err)
  224. }
  225. }
  226. case <-l.quit:
  227. return
  228. }
  229. }
  230. }
  231. // Flush flushs all chan data.
  232. func (l *Logger) Flush() {
  233. for _, l := range l.outputs {
  234. l.Flush()
  235. }
  236. }
  237. // Close closes logger, flush all chan data and destroy all adapter instances.
  238. func (l *Logger) Close() {
  239. l.quit <- true
  240. for {
  241. if len(l.msg) > 0 {
  242. bm := <-l.msg
  243. for _, l := range l.outputs {
  244. if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
  245. fmt.Println("ERROR, unable to WriteMsg:", err)
  246. }
  247. }
  248. } else {
  249. break
  250. }
  251. }
  252. for _, l := range l.outputs {
  253. l.Flush()
  254. l.Destroy()
  255. }
  256. }
  257. // Trace records trace log
  258. func (l *Logger) Trace(format string, v ...interface{}) {
  259. msg := fmt.Sprintf("[T] "+format, v...)
  260. l.writerMsg(0, TRACE, msg)
  261. }
  262. // Debug records debug log
  263. func (l *Logger) Debug(format string, v ...interface{}) {
  264. msg := fmt.Sprintf("[D] "+format, v...)
  265. l.writerMsg(0, DEBUG, msg)
  266. }
  267. // Info records information log
  268. func (l *Logger) Info(format string, v ...interface{}) {
  269. msg := fmt.Sprintf("[I] "+format, v...)
  270. l.writerMsg(0, INFO, msg)
  271. }
  272. // Warn records warnning log
  273. func (l *Logger) Warn(format string, v ...interface{}) {
  274. msg := fmt.Sprintf("[W] "+format, v...)
  275. l.writerMsg(0, WARN, msg)
  276. }
  277. // Error records error log
  278. func (l *Logger) Error(skip int, format string, v ...interface{}) {
  279. msg := fmt.Sprintf("[E] "+format, v...)
  280. l.writerMsg(skip, ERROR, msg)
  281. }
  282. // Critical records critical log
  283. func (l *Logger) Critical(skip int, format string, v ...interface{}) {
  284. msg := fmt.Sprintf("[C] "+format, v...)
  285. l.writerMsg(skip, CRITICAL, msg)
  286. }
  287. // Fatal records error log and exit the process
  288. func (l *Logger) Fatal(skip int, format string, v ...interface{}) {
  289. msg := fmt.Sprintf("[F] "+format, v...)
  290. l.writerMsg(skip, FATAL, msg)
  291. l.Close()
  292. os.Exit(1)
  293. }