1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-25 23:21:45 +00:00
Beego/logs/log.go

439 lines
10 KiB
Go
Raw Normal View History

2014-08-18 08:41:43 +00:00
// Copyright 2014 beego Author. All Rights Reserved.
2014-07-03 15:40:21 +00:00
//
2014-08-18 08:41:43 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2014-07-03 15:40:21 +00:00
//
2014-08-18 08:41:43 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2014-07-03 15:40:21 +00:00
//
2014-08-18 08:41:43 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2015-09-11 15:08:24 +00:00
// Package logs provide a general log interface
2014-08-18 08:41:43 +00:00
// Usage:
//
// import "github.com/astaxie/beego/logs"
//
// log := NewLogger(10000)
// log.SetLogger("console", "")
//
// > the first params stand for how many channel
//
// Use it like this:
//
// log.Trace("trace")
// log.Info("info")
// log.Warn("warning")
// log.Debug("debug")
// log.Critical("critical")
2014-07-03 15:40:21 +00:00
//
2014-08-18 08:41:43 +00:00
// more docs http://beego.me/docs/module/logs.md
2013-08-27 15:48:58 +00:00
package logs
import (
"fmt"
2016-01-12 13:05:06 +00:00
"os"
"path"
"runtime"
2016-01-12 14:54:39 +00:00
"strconv"
2013-08-27 15:48:58 +00:00
"sync"
2016-01-23 08:24:58 +00:00
"time"
2013-08-27 15:48:58 +00:00
)
// RFC5424 log message levels.
2013-08-27 15:48:58 +00:00
const (
LevelEmergency = iota
LevelAlert
2013-08-27 15:48:58 +00:00
LevelCritical
LevelError
LevelWarning
LevelNotice
LevelInformational
LevelDebug
)
// Legacy loglevel constants to ensure backwards compatibility.
//
// Deprecated: will be removed in 1.5.0.
const (
LevelInfo = LevelInformational
LevelTrace = LevelDebug
LevelWarn = LevelWarning
2013-08-27 15:48:58 +00:00
)
2015-09-11 15:08:24 +00:00
type loggerType func() Logger
2013-08-27 15:48:58 +00:00
2015-09-11 15:08:24 +00:00
// Logger defines the behavior of a log provider.
type Logger interface {
2013-08-27 15:48:58 +00:00
Init(config string) error
2016-01-23 08:24:58 +00:00
WriteMsg(when time.Time, msg string, level int) error
2013-08-27 15:48:58 +00:00
Destroy()
2013-11-27 09:50:10 +00:00
Flush()
2013-08-27 15:48:58 +00:00
}
var adapters = make(map[string]loggerType)
// Register makes a log provide available by the provided name.
// If Register is called twice with the same name or if driver is nil,
// it panics.
func Register(name string, log loggerType) {
if log == nil {
panic("logs: Register provide is nil")
}
if _, dup := adapters[name]; dup {
panic("logs: Register called twice for provider " + name)
}
adapters[name] = log
}
2013-12-30 15:32:57 +00:00
// BeeLogger is default logger in beego application.
// it can contain several providers and log message into all providers.
2013-08-27 15:48:58 +00:00
type BeeLogger struct {
lock sync.Mutex
level int
enableFuncCallDepth bool
loggerFuncCallDepth int
asynchronous bool
2016-01-12 14:39:40 +00:00
msgChan chan *logMsg
2016-02-02 09:12:47 +00:00
signalChan chan string
wg sync.WaitGroup
2016-01-12 13:05:06 +00:00
outputs []*nameLogger
}
type nameLogger struct {
Logger
name string
2013-08-27 15:48:58 +00:00
}
type logMsg struct {
level int
msg string
2016-02-03 08:32:59 +00:00
when time.Time
2013-08-27 15:48:58 +00:00
}
2016-01-12 14:39:40 +00:00
var logMsgPool *sync.Pool
2013-12-30 15:32:57 +00:00
// NewLogger returns a new BeeLogger.
2016-01-12 13:05:06 +00:00
// channelLen means the number of messages in chan(used where asynchronous is true).
2013-12-30 15:32:57 +00:00
// if the buffering chan is full, logger adapters write to file or other way.
2016-01-12 13:05:06 +00:00
func NewLogger(channelLen int64) *BeeLogger {
2013-08-27 15:48:58 +00:00
bl := new(BeeLogger)
bl.level = LevelDebug
bl.loggerFuncCallDepth = 2
2016-01-12 14:39:40 +00:00
bl.msgChan = make(chan *logMsg, channelLen)
bl.signalChan = make(chan string, 1)
return bl
}
2015-09-11 15:08:24 +00:00
// Async set the log to asynchronous and start the goroutine
func (bl *BeeLogger) Async() *BeeLogger {
bl.asynchronous = true
2016-01-12 14:39:40 +00:00
logMsgPool = &sync.Pool{
New: func() interface{} {
return &logMsg{}
},
}
2016-02-02 09:12:47 +00:00
bl.wg.Add(1)
2014-04-02 15:43:37 +00:00
go bl.startLogger()
2013-08-27 15:48:58 +00:00
return bl
}
2013-12-30 15:32:57 +00:00
// SetLogger provides a given logger adapter into BeeLogger with config string.
// config need to be correct JSON as string: {"interval":360}.
2016-01-12 13:05:06 +00:00
func (bl *BeeLogger) SetLogger(adapterName string, config string) error {
2013-08-27 15:48:58 +00:00
bl.lock.Lock()
defer bl.lock.Unlock()
2016-03-11 02:12:17 +00:00
for _, l := range bl.outputs {
if l.name == adapterName {
return fmt.Errorf("logs: duplicate adaptername %q (you have set this logger before)", adapterName)
2014-04-02 15:43:37 +00:00
}
2016-03-11 02:12:17 +00:00
}
2016-03-11 05:00:58 +00:00
2016-03-11 02:12:17 +00:00
log, ok := adapters[adapterName]
if !ok {
2016-01-12 13:05:06 +00:00
return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName)
2013-08-27 15:48:58 +00:00
}
2016-03-11 02:12:17 +00:00
lg := log()
err := lg.Init(config)
if err != nil {
fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error())
return err
}
bl.outputs = append(bl.outputs, &nameLogger{name: adapterName, Logger: lg})
return nil
2013-08-27 15:48:58 +00:00
}
2015-09-11 15:08:24 +00:00
// DelLogger remove a logger adapter in BeeLogger.
2016-01-12 13:05:06 +00:00
func (bl *BeeLogger) DelLogger(adapterName string) error {
2013-08-27 15:48:58 +00:00
bl.lock.Lock()
defer bl.lock.Unlock()
2016-01-12 13:05:06 +00:00
outputs := []*nameLogger{}
for _, lg := range bl.outputs {
if lg.name == adapterName {
lg.Destroy()
} else {
outputs = append(outputs, lg)
}
2013-08-27 15:48:58 +00:00
}
2016-01-12 13:05:06 +00:00
if len(outputs) == len(bl.outputs) {
return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName)
}
bl.outputs = outputs
return nil
2013-08-27 15:48:58 +00:00
}
2016-01-23 08:24:58 +00:00
func (bl *BeeLogger) writeToLoggers(when time.Time, msg string, level int) {
for _, l := range bl.outputs {
2016-01-23 08:24:58 +00:00
err := l.WriteMsg(when, msg, level)
if err != nil {
fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err)
}
}
}
func (bl *BeeLogger) Write(p []byte) (n int, err error) {
if len(p) == 0 {
return 0, nil
}
// writeMsg will always add a '\n' character
if p[len(p)-1] == '\n' {
p = p[0 : len(p)-1]
}
// set LevelCritical to ensure all log message will be write out
err = bl.writeMsg(LevelCritical, string(p))
if err == nil {
return len(p), err
}
return 0, err
}
2016-01-12 14:32:20 +00:00
func (bl *BeeLogger) writeMsg(logLevel int, msg string) error {
2016-01-25 12:20:53 +00:00
when := time.Now()
if bl.enableFuncCallDepth {
2014-11-03 08:40:08 +00:00
_, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth)
2015-06-15 12:53:49 +00:00
if !ok {
file = "???"
line = 0
}
2015-06-15 12:53:49 +00:00
_, filename := path.Split(file)
msg = "[" + filename + ":" + strconv.FormatInt(int64(line), 10) + "] " + msg
}
if bl.asynchronous {
2016-01-12 14:39:40 +00:00
lm := logMsgPool.Get().(*logMsg)
2016-01-12 14:32:20 +00:00
lm.level = logLevel
lm.msg = msg
2016-01-23 08:24:58 +00:00
lm.when = when
2016-01-12 14:39:40 +00:00
bl.msgChan <- lm
} else {
2016-01-23 08:24:58 +00:00
bl.writeToLoggers(when, msg, logLevel)
}
2013-08-27 15:48:58 +00:00
return nil
}
2015-09-11 15:08:24 +00:00
// SetLevel Set log message level.
// If message level (such as LevelDebug) is higher than logger level (such as LevelWarning),
// log providers will not even be sent the message.
2013-08-27 15:48:58 +00:00
func (bl *BeeLogger) SetLevel(l int) {
bl.level = l
}
2015-09-11 15:08:24 +00:00
// SetLogFuncCallDepth set log funcCallDepth
func (bl *BeeLogger) SetLogFuncCallDepth(d int) {
bl.loggerFuncCallDepth = d
}
2015-09-11 15:08:24 +00:00
// GetLogFuncCallDepth return log funcCallDepth for wrapper
func (bl *BeeLogger) GetLogFuncCallDepth() int {
return bl.loggerFuncCallDepth
}
2015-09-11 15:08:24 +00:00
// EnableFuncCallDepth enable log funcCallDepth
func (bl *BeeLogger) EnableFuncCallDepth(b bool) {
bl.enableFuncCallDepth = b
}
2013-12-30 15:32:57 +00:00
// start logger chan reading.
// when chan is not empty, write logs.
2014-04-02 15:43:37 +00:00
func (bl *BeeLogger) startLogger() {
2016-02-02 09:12:47 +00:00
gameOver := false
2013-08-27 15:48:58 +00:00
for {
select {
2016-01-12 14:39:40 +00:00
case bm := <-bl.msgChan:
2016-01-23 08:24:58 +00:00
bl.writeToLoggers(bm.when, bm.msg, bm.level)
2016-01-12 14:39:40 +00:00
logMsgPool.Put(bm)
case sg := <-bl.signalChan:
// Now should only send "flush" or "close" to bl.signalChan
2016-02-02 09:12:47 +00:00
bl.flush()
if sg == "close" {
for _, l := range bl.outputs {
l.Destroy()
}
bl.outputs = nil
2016-02-02 09:12:47 +00:00
gameOver = true
}
bl.wg.Done()
2013-08-27 15:48:58 +00:00
}
2016-02-02 09:12:47 +00:00
if gameOver {
break
2013-08-27 15:48:58 +00:00
}
}
}
2015-09-11 15:08:24 +00:00
// Emergency Log EMERGENCY level message.
func (bl *BeeLogger) Emergency(format string, v ...interface{}) {
if LevelEmergency > bl.level {
return
}
msg := fmt.Sprintf("[M] "+format, v...)
bl.writeMsg(LevelEmergency, msg)
2013-08-27 15:48:58 +00:00
}
2015-09-11 15:08:24 +00:00
// Alert Log ALERT level message.
func (bl *BeeLogger) Alert(format string, v ...interface{}) {
if LevelAlert > bl.level {
return
}
msg := fmt.Sprintf("[A] "+format, v...)
bl.writeMsg(LevelAlert, msg)
2013-08-27 15:48:58 +00:00
}
2015-09-11 15:08:24 +00:00
// Critical Log CRITICAL level message.
func (bl *BeeLogger) Critical(format string, v ...interface{}) {
if LevelCritical > bl.level {
return
}
msg := fmt.Sprintf("[C] "+format, v...)
bl.writeMsg(LevelCritical, msg)
}
2015-09-11 15:08:24 +00:00
// Error Log ERROR level message.
func (bl *BeeLogger) Error(format string, v ...interface{}) {
if LevelError > bl.level {
return
}
msg := fmt.Sprintf("[E] "+format, v...)
bl.writeMsg(LevelError, msg)
}
2015-09-11 15:08:24 +00:00
// Warning Log WARNING level message.
func (bl *BeeLogger) Warning(format string, v ...interface{}) {
if LevelWarning > bl.level {
return
}
msg := fmt.Sprintf("[W] "+format, v...)
bl.writeMsg(LevelWarning, msg)
}
2015-09-11 15:08:24 +00:00
// Notice Log NOTICE level message.
func (bl *BeeLogger) Notice(format string, v ...interface{}) {
if LevelNotice > bl.level {
return
}
msg := fmt.Sprintf("[N] "+format, v...)
bl.writeMsg(LevelNotice, msg)
}
2015-09-11 15:08:24 +00:00
// Informational Log INFORMATIONAL level message.
func (bl *BeeLogger) Informational(format string, v ...interface{}) {
if LevelInformational > bl.level {
return
}
2013-08-27 15:48:58 +00:00
msg := fmt.Sprintf("[I] "+format, v...)
bl.writeMsg(LevelInformational, msg)
2013-08-27 15:48:58 +00:00
}
2015-09-11 15:08:24 +00:00
// Debug Log DEBUG level message.
func (bl *BeeLogger) Debug(format string, v ...interface{}) {
if LevelDebug > bl.level {
return
}
msg := fmt.Sprintf("[D] "+format, v...)
bl.writeMsg(LevelDebug, msg)
}
2015-09-11 15:08:24 +00:00
// Warn Log WARN level message.
2015-06-15 12:22:05 +00:00
// compatibility alias for Warning()
2013-08-27 15:48:58 +00:00
func (bl *BeeLogger) Warn(format string, v ...interface{}) {
2015-06-15 12:20:37 +00:00
if LevelWarning > bl.level {
return
}
msg := fmt.Sprintf("[W] "+format, v...)
bl.writeMsg(LevelWarning, msg)
2013-08-27 15:48:58 +00:00
}
2015-09-11 15:08:24 +00:00
// Info Log INFO level message.
2015-06-15 12:22:05 +00:00
// compatibility alias for Informational()
func (bl *BeeLogger) Info(format string, v ...interface{}) {
2015-06-15 12:20:37 +00:00
if LevelInformational > bl.level {
return
}
msg := fmt.Sprintf("[I] "+format, v...)
bl.writeMsg(LevelInformational, msg)
2013-08-27 15:48:58 +00:00
}
2015-09-11 15:08:24 +00:00
// Trace Log TRACE level message.
2015-06-15 12:22:05 +00:00
// compatibility alias for Debug()
func (bl *BeeLogger) Trace(format string, v ...interface{}) {
2015-06-15 12:20:37 +00:00
if LevelDebug > bl.level {
return
}
msg := fmt.Sprintf("[D] "+format, v...)
bl.writeMsg(LevelDebug, msg)
2013-08-27 15:48:58 +00:00
}
2015-09-11 15:08:24 +00:00
// Flush flush all chan data.
2013-11-27 09:50:10 +00:00
func (bl *BeeLogger) Flush() {
2016-02-02 09:12:47 +00:00
if bl.asynchronous {
bl.signalChan <- "flush"
bl.wg.Wait()
bl.wg.Add(1)
return
2013-11-27 09:50:10 +00:00
}
2016-02-02 09:12:47 +00:00
bl.flush()
2013-11-27 09:50:10 +00:00
}
2015-09-11 15:08:24 +00:00
// Close close logger, flush all chan data and destroy all adapters in BeeLogger.
2013-08-27 15:48:58 +00:00
func (bl *BeeLogger) Close() {
2016-02-02 09:12:47 +00:00
if bl.asynchronous {
bl.signalChan <- "close"
bl.wg.Wait()
} else {
bl.flush()
for _, l := range bl.outputs {
l.Destroy()
}
bl.outputs = nil
}
close(bl.msgChan)
close(bl.signalChan)
}
// Reset close all outputs, and set bl.outputs to nil
func (bl *BeeLogger) Reset() {
bl.Flush()
for _, l := range bl.outputs {
l.Destroy()
}
bl.outputs = nil
}
func (bl *BeeLogger) flush() {
2013-11-27 09:50:10 +00:00
for {
2016-01-12 14:39:40 +00:00
if len(bl.msgChan) > 0 {
bm := <-bl.msgChan
2016-01-23 08:24:58 +00:00
bl.writeToLoggers(bm.when, bm.msg, bm.level)
2016-01-12 14:39:40 +00:00
logMsgPool.Put(bm)
2015-02-23 03:42:46 +00:00
continue
2013-11-27 09:50:10 +00:00
}
2015-02-23 03:42:46 +00:00
break
2013-11-27 09:50:10 +00:00
}
2013-08-27 15:48:58 +00:00
for _, l := range bl.outputs {
2013-11-27 09:50:10 +00:00
l.Flush()
2013-08-27 15:48:58 +00:00
}
}