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.

log.go 7.7KB

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. }