Beego/logs/log.go

412 lines
9.5 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-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-01-23 08:24:58 +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)
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{}
},
}
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-01-12 13:05:06 +00:00
if log, ok := adapters[adapterName]; ok {
2013-08-27 15:48:58 +00:00
lg := log()
2014-04-02 15:43:37 +00:00
err := lg.Init(config)
if err != nil {
2016-01-12 13:05:06 +00:00
fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error())
2014-04-02 15:43:37 +00:00
return err
}
2016-01-12 13:05:06 +00:00
bl.outputs = append(bl.outputs, &nameLogger{name: adapterName, Logger: lg})
2013-08-27 15:48:58 +00:00
} else {
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
}
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)
}
}
}
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)
2016-01-12 14:54:39 +00:00
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() {
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)
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() {
for _, l := range bl.outputs {
l.Flush()
}
}
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() {
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
l.Destroy()
}
2016-01-26 16:42:07 +00:00
bl.outputs = nil
2013-08-27 15:48:58 +00:00
}
2016-01-23 08:24:58 +00:00
func formatLogTime(when time.Time) string {
y, mo, d := when.Date()
h, mi, s := when.Clock()
//len(2006/01/02 15:03:04)==19
var buf [20]byte
t := 3
for y >= 10 {
p := y / 10
buf[t] = byte('0' + y - p*10)
y = p
t--
}
buf[0] = byte('0' + y)
buf[4] = '/'
if mo > 9 {
buf[5] = '1'
buf[6] = byte('0' + mo - 9)
} else {
buf[5] = '0'
buf[6] = byte('0' + mo)
}
buf[7] = '/'
t = d / 10
buf[8] = byte('0' + t)
buf[9] = byte('0' + d - t*10)
buf[10] = ' '
t = h / 10
buf[11] = byte('0' + t)
buf[12] = byte('0' + h - t*10)
buf[13] = ':'
t = mi / 10
buf[14] = byte('0' + t)
buf[15] = byte('0' + mi - t*10)
buf[16] = ':'
t = s / 10
buf[17] = byte('0' + t)
buf[18] = byte('0' + s - t*10)
buf[19] = ' '
return string(buf[0:])
}