Beego/logs/log.go

357 lines
8.4 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.
// 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"
"path"
"runtime"
2013-08-27 15:48:58 +00:00
"sync"
)
// 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
)
type loggerType func() LoggerInterface
2013-12-30 15:32:57 +00:00
// LoggerInterface defines the behavior of a log provider.
2013-08-27 15:48:58 +00:00
type LoggerInterface interface {
Init(config string) error
WriteMsg(msg string, level int) error
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
msg chan *logMsg
outputs map[string]LoggerInterface
2013-08-27 15:48:58 +00:00
}
type logMsg struct {
level int
msg string
}
2013-12-30 15:32:57 +00:00
// NewLogger returns a new BeeLogger.
// channellen means the number of messages in chan.
// if the buffering chan is full, logger adapters write to file or other way.
2013-08-27 15:48:58 +00:00
func NewLogger(channellen int64) *BeeLogger {
bl := new(BeeLogger)
bl.level = LevelDebug
bl.loggerFuncCallDepth = 2
2013-08-27 15:48:58 +00:00
bl.msg = make(chan *logMsg, channellen)
bl.outputs = make(map[string]LoggerInterface)
return bl
}
func (bl *BeeLogger) Async() *BeeLogger {
bl.asynchronous = true
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}.
2013-08-27 15:48:58 +00:00
func (bl *BeeLogger) SetLogger(adaptername string, config string) error {
bl.lock.Lock()
defer bl.lock.Unlock()
if log, ok := adapters[adaptername]; ok {
lg := log()
2014-04-02 15:43:37 +00:00
err := lg.Init(config)
bl.outputs[adaptername] = lg
2014-04-02 15:43:37 +00:00
if err != nil {
fmt.Println("logs.BeeLogger.SetLogger: " + err.Error())
2014-04-02 15:43:37 +00:00
return err
}
2013-08-27 15:48:58 +00:00
} else {
return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adaptername)
}
return nil
2013-08-27 15:48:58 +00:00
}
2013-12-30 15:32:57 +00:00
// remove a logger adapter in BeeLogger.
2013-08-27 15:48:58 +00:00
func (bl *BeeLogger) DelLogger(adaptername string) error {
bl.lock.Lock()
defer bl.lock.Unlock()
if lg, ok := bl.outputs[adaptername]; ok {
lg.Destroy()
delete(bl.outputs, adaptername)
return nil
} else {
return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adaptername)
}
}
func (bl *BeeLogger) writerMsg(loglevel int, msg string) error {
lm := new(logMsg)
lm.level = loglevel
if bl.enableFuncCallDepth {
2014-11-03 08:40:08 +00:00
_, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth)
if _, filename := path.Split(file); filename == "log.go" && (line == 97 || line == 83) {
2014-11-03 08:44:05 +00:00
_, file, line, ok = runtime.Caller(bl.loggerFuncCallDepth + 1)
}
if ok {
_, filename := path.Split(file)
lm.msg = fmt.Sprintf("[%s:%d] %s", filename, line, msg)
} else {
lm.msg = msg
}
} else {
lm.msg = msg
}
if bl.asynchronous {
bl.msg <- lm
} else {
for name, l := range bl.outputs {
err := l.WriteMsg(lm.msg, lm.level)
if err != nil {
fmt.Println("unable to WriteMsg to adapter:", name, err)
return err
}
}
}
2013-08-27 15:48:58 +00:00
return nil
}
// 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
}
// set log funcCallDepth
func (bl *BeeLogger) SetLogFuncCallDepth(d int) {
bl.loggerFuncCallDepth = d
}
// get log funcCallDepth for wrapper
func (bl *BeeLogger) GetLogFuncCallDepth() int {
return bl.loggerFuncCallDepth
}
// 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 {
case bm := <-bl.msg:
for _, l := range bl.outputs {
2014-08-26 04:37:35 +00:00
err := l.WriteMsg(bm.msg, bm.level)
if err != nil {
fmt.Println("ERROR, unable to WriteMsg:", err)
}
2013-08-27 15:48:58 +00:00
}
}
}
}
// Log EMERGENCY level message.
func (bl *BeeLogger) Emergency(format string, v ...interface{}) {
if LevelEmergency > bl.level {
return
}
msg := fmt.Sprintf("[M] "+format, v...)
bl.writerMsg(LevelEmergency, msg)
2013-08-27 15:48:58 +00:00
}
// Log ALERT level message.
func (bl *BeeLogger) Alert(format string, v ...interface{}) {
if LevelAlert > bl.level {
return
}
msg := fmt.Sprintf("[A] "+format, v...)
bl.writerMsg(LevelAlert, msg)
2013-08-27 15:48:58 +00:00
}
// Log CRITICAL level message.
func (bl *BeeLogger) Critical(format string, v ...interface{}) {
if LevelCritical > bl.level {
return
}
msg := fmt.Sprintf("[C] "+format, v...)
bl.writerMsg(LevelCritical, msg)
}
// Log ERROR level message.
func (bl *BeeLogger) Error(format string, v ...interface{}) {
if LevelError > bl.level {
return
}
msg := fmt.Sprintf("[E] "+format, v...)
bl.writerMsg(LevelError, msg)
}
// Log WARNING level message.
func (bl *BeeLogger) Warning(format string, v ...interface{}) {
if LevelWarning > bl.level {
return
}
msg := fmt.Sprintf("[W] "+format, v...)
bl.writerMsg(LevelWarning, msg)
}
// Log NOTICE level message.
func (bl *BeeLogger) Notice(format string, v ...interface{}) {
if LevelNotice > bl.level {
return
}
msg := fmt.Sprintf("[N] "+format, v...)
bl.writerMsg(LevelNotice, msg)
}
// 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.writerMsg(LevelInformational, msg)
2013-08-27 15:48:58 +00:00
}
// Log DEBUG level message.
func (bl *BeeLogger) Debug(format string, v ...interface{}) {
if LevelDebug > bl.level {
return
}
msg := fmt.Sprintf("[D] "+format, v...)
bl.writerMsg(LevelDebug, msg)
}
// Log WARN level message.
//
// Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0.
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.writerMsg(LevelWarning, msg)
2013-08-27 15:48:58 +00:00
}
// Log INFO level message.
//
// Deprecated: compatibility alias for Informational(), Will be removed in 1.5.0.
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.writerMsg(LevelInformational, msg)
2013-08-27 15:48:58 +00:00
}
// Log TRACE level message.
//
// Deprecated: compatibility alias for Debug(), Will be removed in 1.5.0.
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.writerMsg(LevelDebug, msg)
2013-08-27 15:48:58 +00:00
}
2013-12-30 15:32:57 +00:00
// flush all chan data.
2013-11-27 09:50:10 +00:00
func (bl *BeeLogger) Flush() {
for _, l := range bl.outputs {
l.Flush()
}
}
2013-12-30 15:32:57 +00:00
// 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 {
if len(bl.msg) > 0 {
bm := <-bl.msg
for _, l := range bl.outputs {
2014-08-26 04:37:35 +00:00
err := l.WriteMsg(bm.msg, bm.level)
if err != nil {
fmt.Println("ERROR, unable to WriteMsg (while closing logger):", err)
}
2013-11-27 09:50:10 +00:00
}
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()
}
}