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.

312 lines
6.6 KiB

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