forgejo/modules/log/log.go

308 lines
6.5 KiB
Go
Raw Normal View History

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