123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- // Copyright 2014 The Gogs Authors. All rights reserved.
- // Use of this source code is governed by a MIT-style
- // license that can be found in the LICENSE file.
- package log
- import (
- "fmt"
- "os"
- "path"
- "path/filepath"
- "runtime"
- "strings"
- "sync"
- )
- var (
- loggers []*Logger
- GitLogger *Logger
- )
- func NewLogger(bufLen int64, mode, config string) {
- logger := newLogger(bufLen)
- isExist := false
- for i, l := range loggers {
- if l.adapter == mode {
- isExist = true
- loggers[i] = logger
- }
- }
- if !isExist {
- loggers = append(loggers, logger)
- }
- if err := logger.SetLogger(mode, config); err != nil {
- Fatal(2, "Fail to set logger (%s): %v", mode, err)
- }
- }
- // FIXME: use same log level as other loggers.
- func NewGitLogger(logPath string) {
- os.MkdirAll(path.Dir(logPath), os.ModePerm)
- GitLogger = newLogger(0)
- GitLogger.SetLogger("file", fmt.Sprintf(`{"level":0,"filename":"%s","rotate":false}`, logPath))
- }
- func Trace(format string, v ...interface{}) {
- for _, logger := range loggers {
- logger.Trace(format, v...)
- }
- }
- func Debug(format string, v ...interface{}) {
- for _, logger := range loggers {
- logger.Debug(format, v...)
- }
- }
- func Info(format string, v ...interface{}) {
- for _, logger := range loggers {
- logger.Info(format, v...)
- }
- }
- func Warn(format string, v ...interface{}) {
- for _, logger := range loggers {
- logger.Warn(format, v...)
- }
- }
- func Error(skip int, format string, v ...interface{}) {
- for _, logger := range loggers {
- logger.Error(skip, format, v...)
- }
- }
- func Critical(skip int, format string, v ...interface{}) {
- for _, logger := range loggers {
- logger.Critical(skip, format, v...)
- }
- }
- func Fatal(skip int, format string, v ...interface{}) {
- Error(skip, format, v...)
- for _, l := range loggers {
- l.Close()
- }
- os.Exit(1)
- }
- func Close() {
- for _, l := range loggers {
- l.Close()
- }
- }
- // .___ __ _____
- // | | _____/ |_ ____________/ ____\____ ____ ____
- // | |/ \ __\/ __ \_ __ \ __\\__ \ _/ ___\/ __ \
- // | | | \ | \ ___/| | \/| | / __ \\ \__\ ___/
- // |___|___| /__| \___ >__| |__| (____ /\___ >___ >
- // \/ \/ \/ \/ \/
- type LogLevel int
- const (
- TRACE = iota
- DEBUG
- INFO
- WARN
- ERROR
- CRITICAL
- FATAL
- )
- // LoggerInterface represents behaviors of a logger provider.
- type LoggerInterface interface {
- Init(config string) error
- WriteMsg(msg string, skip, level int) error
- Destroy()
- Flush()
- }
- type loggerType func() LoggerInterface
- var adapters = make(map[string]loggerType)
- // Register registers given logger provider to adapters.
- func Register(name string, log loggerType) {
- if log == nil {
- panic("log: register provider is nil")
- }
- if _, dup := adapters[name]; dup {
- panic("log: register called twice for provider \"" + name + "\"")
- }
- adapters[name] = log
- }
- type logMsg struct {
- skip, level int
- msg string
- }
- // Logger is default logger in beego application.
- // it can contain several providers and log message into all providers.
- type Logger struct {
- adapter string
- lock sync.Mutex
- level int
- msg chan *logMsg
- outputs map[string]LoggerInterface
- quit chan bool
- }
- // newLogger initializes and returns a new logger.
- func newLogger(buffer int64) *Logger {
- l := &Logger{
- msg: make(chan *logMsg, buffer),
- outputs: make(map[string]LoggerInterface),
- quit: make(chan bool),
- }
- go l.StartLogger()
- return l
- }
- // SetLogger sets new logger instance with given logger adapter and config.
- func (l *Logger) SetLogger(adapter string, config string) error {
- l.lock.Lock()
- defer l.lock.Unlock()
- if log, ok := adapters[adapter]; ok {
- lg := log()
- if err := lg.Init(config); err != nil {
- return err
- }
- l.outputs[adapter] = lg
- l.adapter = adapter
- } else {
- panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
- }
- return nil
- }
- // DelLogger removes a logger adapter instance.
- func (l *Logger) DelLogger(adapter string) error {
- l.lock.Lock()
- defer l.lock.Unlock()
- if lg, ok := l.outputs[adapter]; ok {
- lg.Destroy()
- delete(l.outputs, adapter)
- } else {
- panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
- }
- return nil
- }
- func (l *Logger) writerMsg(skip, level int, msg string) error {
- if l.level > level {
- return nil
- }
- lm := &logMsg{
- skip: skip,
- level: level,
- }
- // Only error information needs locate position for debugging.
- if lm.level >= ERROR {
- pc, file, line, ok := runtime.Caller(skip)
- if ok {
- // Get caller function name.
- fn := runtime.FuncForPC(pc)
- var fnName string
- if fn == nil {
- fnName = "?()"
- } else {
- fnName = strings.TrimLeft(filepath.Ext(fn.Name()), ".") + "()"
- }
- fileName := file
- if len(fileName) > 20 {
- fileName = "..." + fileName[len(fileName)-20:]
- }
- lm.msg = fmt.Sprintf("[%s:%d %s] %s", fileName, line, fnName, msg)
- } else {
- lm.msg = msg
- }
- } else {
- lm.msg = msg
- }
- l.msg <- lm
- return nil
- }
- // StartLogger starts logger chan reading.
- func (l *Logger) StartLogger() {
- for {
- select {
- case bm := <-l.msg:
- for _, l := range l.outputs {
- if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
- fmt.Println("ERROR, unable to WriteMsg:", err)
- }
- }
- case <-l.quit:
- return
- }
- }
- }
- // Flush flushs all chan data.
- func (l *Logger) Flush() {
- for _, l := range l.outputs {
- l.Flush()
- }
- }
- // Close closes logger, flush all chan data and destroy all adapter instances.
- func (l *Logger) Close() {
- l.quit <- true
- for {
- if len(l.msg) > 0 {
- bm := <-l.msg
- for _, l := range l.outputs {
- if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
- fmt.Println("ERROR, unable to WriteMsg:", err)
- }
- }
- } else {
- break
- }
- }
- for _, l := range l.outputs {
- l.Flush()
- l.Destroy()
- }
- }
- func (l *Logger) Trace(format string, v ...interface{}) {
- msg := fmt.Sprintf("[T] "+format, v...)
- l.writerMsg(0, TRACE, msg)
- }
- func (l *Logger) Debug(format string, v ...interface{}) {
- msg := fmt.Sprintf("[D] "+format, v...)
- l.writerMsg(0, DEBUG, msg)
- }
- func (l *Logger) Info(format string, v ...interface{}) {
- msg := fmt.Sprintf("[I] "+format, v...)
- l.writerMsg(0, INFO, msg)
- }
- func (l *Logger) Warn(format string, v ...interface{}) {
- msg := fmt.Sprintf("[W] "+format, v...)
- l.writerMsg(0, WARN, msg)
- }
- func (l *Logger) Error(skip int, format string, v ...interface{}) {
- msg := fmt.Sprintf("[E] "+format, v...)
- l.writerMsg(skip, ERROR, msg)
- }
- func (l *Logger) Critical(skip int, format string, v ...interface{}) {
- msg := fmt.Sprintf("[C] "+format, v...)
- l.writerMsg(skip, CRITICAL, msg)
- }
- func (l *Logger) Fatal(skip int, format string, v ...interface{}) {
- msg := fmt.Sprintf("[F] "+format, v...)
- l.writerMsg(skip, FATAL, msg)
- l.Close()
- os.Exit(1)
- }
|