2014-02-12 20:54:09 +01:00
|
|
|
// 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 (
|
2014-06-20 07:14:54 +02:00
|
|
|
"fmt"
|
2014-05-26 02:11:25 +02:00
|
|
|
"os"
|
2014-06-20 07:14:54 +02:00
|
|
|
"path"
|
2014-07-26 06:24:27 +02:00
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
2014-02-12 20:54:09 +01:00
|
|
|
)
|
|
|
|
|
2014-03-25 12:47:04 +01:00
|
|
|
var (
|
2014-07-26 06:24:27 +02:00
|
|
|
loggers []*Logger
|
|
|
|
GitLogger *Logger
|
2014-03-25 12:47:04 +01:00
|
|
|
)
|
2014-02-12 20:54:09 +01:00
|
|
|
|
2014-03-19 09:08:25 +01:00
|
|
|
func NewLogger(bufLen int64, mode, config string) {
|
2014-07-26 06:24:27 +02:00
|
|
|
logger := newLogger(bufLen)
|
2014-05-11 20:37:12 +02:00
|
|
|
|
|
|
|
isExist := false
|
|
|
|
for _, l := range loggers {
|
2014-07-26 06:24:27 +02:00
|
|
|
if l.adapter == mode {
|
2014-05-11 20:37:12 +02:00
|
|
|
isExist = true
|
|
|
|
l = logger
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !isExist {
|
|
|
|
loggers = append(loggers, logger)
|
|
|
|
}
|
2014-06-20 06:25:23 +02:00
|
|
|
if err := logger.SetLogger(mode, config); err != nil {
|
2015-12-07 17:33:04 +01:00
|
|
|
Fatal(2, "Fail to set logger (%s): %v", mode, err)
|
2014-06-20 06:25:23 +02:00
|
|
|
}
|
2014-02-12 20:54:09 +01:00
|
|
|
}
|
|
|
|
|
2016-02-16 05:11:22 +01:00
|
|
|
// FIXME: use same log level as other loggers.
|
2014-06-20 07:14:54 +02:00
|
|
|
func NewGitLogger(logPath string) {
|
|
|
|
os.MkdirAll(path.Dir(logPath), os.ModePerm)
|
2014-07-26 06:24:27 +02:00
|
|
|
GitLogger = newLogger(0)
|
2014-06-20 07:14:54 +02:00
|
|
|
GitLogger.SetLogger("file", fmt.Sprintf(`{"level":0,"filename":"%s","rotate":false}`, logPath))
|
|
|
|
}
|
|
|
|
|
2014-02-18 23:48:02 +01:00
|
|
|
func Trace(format string, v ...interface{}) {
|
2014-05-11 20:37:12 +02:00
|
|
|
for _, logger := range loggers {
|
|
|
|
logger.Trace(format, v...)
|
|
|
|
}
|
2014-02-18 23:48:02 +01:00
|
|
|
}
|
|
|
|
|
2014-03-23 17:16:17 +01:00
|
|
|
func Debug(format string, v ...interface{}) {
|
2014-05-11 20:37:12 +02:00
|
|
|
for _, logger := range loggers {
|
|
|
|
logger.Debug(format, v...)
|
|
|
|
}
|
2014-03-23 17:16:17 +01:00
|
|
|
}
|
|
|
|
|
2014-02-12 20:54:09 +01:00
|
|
|
func Info(format string, v ...interface{}) {
|
2014-05-11 20:37:12 +02:00
|
|
|
for _, logger := range loggers {
|
|
|
|
logger.Info(format, v...)
|
|
|
|
}
|
2014-02-12 20:54:09 +01:00
|
|
|
}
|
2014-02-18 23:31:16 +01:00
|
|
|
|
2014-07-26 06:24:27 +02:00
|
|
|
func Warn(format string, v ...interface{}) {
|
2014-05-11 20:37:12 +02:00
|
|
|
for _, logger := range loggers {
|
2014-07-26 06:24:27 +02:00
|
|
|
logger.Warn(format, v...)
|
2014-05-11 20:37:12 +02:00
|
|
|
}
|
2014-02-18 23:31:16 +01:00
|
|
|
}
|
|
|
|
|
2014-07-26 06:24:27 +02:00
|
|
|
func Error(skip int, format string, v ...interface{}) {
|
2014-05-11 20:37:12 +02:00
|
|
|
for _, logger := range loggers {
|
2014-07-26 06:24:27 +02:00
|
|
|
logger.Error(skip, format, v...)
|
2014-05-11 20:37:12 +02:00
|
|
|
}
|
2014-02-18 23:31:16 +01:00
|
|
|
}
|
2014-02-18 23:48:02 +01:00
|
|
|
|
2014-07-26 06:24:27 +02:00
|
|
|
func Critical(skip int, format string, v ...interface{}) {
|
2014-05-11 20:37:12 +02:00
|
|
|
for _, logger := range loggers {
|
2014-07-26 06:24:27 +02:00
|
|
|
logger.Critical(skip, format, v...)
|
2014-05-11 20:37:12 +02:00
|
|
|
}
|
2014-02-18 23:48:02 +01:00
|
|
|
}
|
2014-05-26 02:11:25 +02:00
|
|
|
|
2014-07-26 06:24:27 +02:00
|
|
|
func Fatal(skip int, format string, v ...interface{}) {
|
|
|
|
Error(skip, format, v...)
|
2014-05-26 02:11:25 +02:00
|
|
|
for _, l := range loggers {
|
|
|
|
l.Close()
|
|
|
|
}
|
2014-07-26 06:24:27 +02:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2014-09-22 23:30:58 +02:00
|
|
|
func Close() {
|
|
|
|
for _, l := range loggers {
|
|
|
|
l.Close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-27 00:37:18 +02:00
|
|
|
// .___ __ _____
|
|
|
|
// | | _____/ |_ ____________/ ____\____ ____ ____
|
|
|
|
// | |/ \ __\/ __ \_ __ \ __\\__ \ _/ ___\/ __ \
|
|
|
|
// | | | \ | \ ___/| | \/| | / __ \\ \__\ ___/
|
|
|
|
// |___|___| /__| \___ >__| |__| (____ /\___ >___ >
|
|
|
|
// \/ \/ \/ \/ \/
|
2014-07-26 06:24:27 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2014-12-07 02:22:48 +01:00
|
|
|
// SetLogger sets new logger instance with given logger adapter and config.
|
2014-07-26 06:24:27 +02:00
|
|
|
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 {
|
2014-07-27 00:37:18 +02:00
|
|
|
panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
|
2014-07-26 06:24:27 +02:00
|
|
|
}
|
|
|
|
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 {
|
2014-07-27 00:37:18 +02:00
|
|
|
panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
|
2014-07-26 06:24:27 +02:00
|
|
|
}
|
|
|
|
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()), ".") + "()"
|
|
|
|
}
|
|
|
|
|
2015-07-26 16:06:28 +02:00
|
|
|
fileName := file
|
|
|
|
if len(fileName) > 20 {
|
|
|
|
fileName = "..." + fileName[len(fileName)-20:]
|
|
|
|
}
|
|
|
|
lm.msg = fmt.Sprintf("[%s:%d %s] %s", fileName, line, fnName, msg)
|
2014-07-26 06:24:27 +02:00
|
|
|
} 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 {
|
2014-08-27 10:39:36 +02:00
|
|
|
if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
|
|
|
|
fmt.Println("ERROR, unable to WriteMsg:", err)
|
|
|
|
}
|
2014-07-26 06:24:27 +02:00
|
|
|
}
|
|
|
|
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 {
|
2014-08-27 10:39:36 +02:00
|
|
|
if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil {
|
|
|
|
fmt.Println("ERROR, unable to WriteMsg:", err)
|
|
|
|
}
|
2014-07-26 06:24:27 +02:00
|
|
|
}
|
|
|
|
} 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)
|
2014-05-26 02:11:25 +02:00
|
|
|
}
|