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 8.8 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  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. // LoggerAsWriter is a io.Writer shim around the gitea log
  133. type LoggerAsWriter struct {
  134. level int
  135. }
  136. // NewLoggerAsWriter creates a Writer representation of the logger with setable log level
  137. func NewLoggerAsWriter(level string) *LoggerAsWriter {
  138. l := &LoggerAsWriter{}
  139. switch strings.ToUpper(level) {
  140. case "TRACE":
  141. l.level = TRACE
  142. case "DEBUG":
  143. l.level = DEBUG
  144. case "INFO":
  145. l.level = INFO
  146. case "WARN":
  147. l.level = WARN
  148. case "ERROR":
  149. l.level = ERROR
  150. case "CRITICAL":
  151. l.level = CRITICAL
  152. case "FATAL":
  153. l.level = FATAL
  154. default:
  155. l.level = INFO
  156. }
  157. return l
  158. }
  159. // Write implements the io.Writer interface to allow spoofing of macaron
  160. func (l *LoggerAsWriter) Write(p []byte) (int, error) {
  161. l.Log(string(p))
  162. return len(p), nil
  163. }
  164. // Log takes a given string and logs it at the set log-level
  165. func (l *LoggerAsWriter) Log(msg string) {
  166. for _, logger := range loggers {
  167. logger.writerMsg(0, l.level, msg)
  168. }
  169. }
  170. var adapters = make(map[string]loggerType)
  171. // Register registers given logger provider to adapters.
  172. func Register(name string, log loggerType) {
  173. if log == nil {
  174. panic("log: register provider is nil")
  175. }
  176. if _, dup := adapters[name]; dup {
  177. panic("log: register called twice for provider \"" + name + "\"")
  178. }
  179. adapters[name] = log
  180. }
  181. type logMsg struct {
  182. skip, level int
  183. msg string
  184. }
  185. // Logger is default logger in beego application.
  186. // it can contain several providers and log message into all providers.
  187. type Logger struct {
  188. adapter string
  189. level int
  190. msg chan *logMsg
  191. outputs syncmap.Map
  192. quit chan bool
  193. }
  194. // newLogger initializes and returns a new logger.
  195. func newLogger(buffer int64) *Logger {
  196. l := &Logger{
  197. msg: make(chan *logMsg, buffer),
  198. quit: make(chan bool),
  199. }
  200. go l.StartLogger()
  201. return l
  202. }
  203. // SetLogger sets new logger instance with given logger adapter and config.
  204. func (l *Logger) SetLogger(adapter string, config string) error {
  205. if log, ok := adapters[adapter]; ok {
  206. lg := log()
  207. if err := lg.Init(config); err != nil {
  208. return err
  209. }
  210. l.outputs.Store(adapter, lg)
  211. l.adapter = adapter
  212. } else {
  213. panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
  214. }
  215. return nil
  216. }
  217. // DelLogger removes a logger adapter instance.
  218. func (l *Logger) DelLogger(adapter string) error {
  219. if lg, ok := l.outputs.Load(adapter); ok {
  220. lg.(LoggerInterface).Destroy()
  221. l.outputs.Delete(adapter)
  222. } else {
  223. panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
  224. }
  225. return nil
  226. }
  227. func (l *Logger) writerMsg(skip, level int, msg string) error {
  228. if l.level > level {
  229. return nil
  230. }
  231. lm := &logMsg{
  232. skip: skip,
  233. level: level,
  234. }
  235. // Only error information needs locate position for debugging.
  236. if lm.level >= ERROR {
  237. pc, file, line, ok := runtime.Caller(skip)
  238. if ok {
  239. // Get caller function name.
  240. fn := runtime.FuncForPC(pc)
  241. var fnName string
  242. if fn == nil {
  243. fnName = "?()"
  244. } else {
  245. fnName = strings.TrimLeft(filepath.Ext(fn.Name()), ".") + "()"
  246. }
  247. fileName := file
  248. if len(fileName) > 20 {
  249. fileName = "..." + fileName[len(fileName)-20:]
  250. }
  251. lm.msg = fmt.Sprintf("[%s:%d %s] %s", fileName, line, fnName, msg)
  252. } else {
  253. lm.msg = msg
  254. }
  255. } else {
  256. lm.msg = msg
  257. }
  258. l.msg <- lm
  259. return nil
  260. }
  261. // StartLogger starts logger chan reading.
  262. func (l *Logger) StartLogger() {
  263. for {
  264. select {
  265. case bm := <-l.msg:
  266. l.outputs.Range(func(k, v interface{}) bool {
  267. if err := v.(LoggerInterface).WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
  268. fmt.Println("ERROR, unable to WriteMsg:", err)
  269. }
  270. return true
  271. })
  272. case <-l.quit:
  273. return
  274. }
  275. }
  276. }
  277. // Flush flushes all chan data.
  278. func (l *Logger) Flush() {
  279. l.outputs.Range(func(k, v interface{}) bool {
  280. v.(LoggerInterface).Flush()
  281. return true
  282. })
  283. }
  284. // Close closes logger, flush all chan data and destroy all adapter instances.
  285. func (l *Logger) Close() {
  286. l.quit <- true
  287. for {
  288. if len(l.msg) > 0 {
  289. bm := <-l.msg
  290. l.outputs.Range(func(k, v interface{}) bool {
  291. if err := v.(LoggerInterface).WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
  292. fmt.Println("ERROR, unable to WriteMsg:", err)
  293. }
  294. return true
  295. })
  296. } else {
  297. break
  298. }
  299. }
  300. l.outputs.Range(func(k, v interface{}) bool {
  301. v.(LoggerInterface).Flush()
  302. v.(LoggerInterface).Destroy()
  303. return true
  304. })
  305. }
  306. // Trace records trace log
  307. func (l *Logger) Trace(format string, v ...interface{}) {
  308. msg := fmt.Sprintf("[T] "+format, v...)
  309. l.writerMsg(0, TRACE, msg)
  310. }
  311. // Debug records debug log
  312. func (l *Logger) Debug(format string, v ...interface{}) {
  313. msg := fmt.Sprintf("[D] "+format, v...)
  314. l.writerMsg(0, DEBUG, msg)
  315. }
  316. // Info records information log
  317. func (l *Logger) Info(format string, v ...interface{}) {
  318. msg := fmt.Sprintf("[I] "+format, v...)
  319. l.writerMsg(0, INFO, msg)
  320. }
  321. // Warn records warning log
  322. func (l *Logger) Warn(format string, v ...interface{}) {
  323. msg := fmt.Sprintf("[W] "+format, v...)
  324. l.writerMsg(0, WARN, msg)
  325. }
  326. // Error records error log
  327. func (l *Logger) Error(skip int, format string, v ...interface{}) {
  328. msg := fmt.Sprintf("[E] "+format, v...)
  329. l.writerMsg(skip, ERROR, msg)
  330. }
  331. // Critical records critical log
  332. func (l *Logger) Critical(skip int, format string, v ...interface{}) {
  333. msg := fmt.Sprintf("[C] "+format, v...)
  334. l.writerMsg(skip, CRITICAL, msg)
  335. }
  336. // Fatal records error log and exit the process
  337. func (l *Logger) Fatal(skip int, format string, v ...interface{}) {
  338. msg := fmt.Sprintf("[F] "+format, v...)
  339. l.writerMsg(skip, FATAL, msg)
  340. l.Close()
  341. os.Exit(1)
  342. }