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.9 kB

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