add SetHandler, enhance threadsafe

This commit is contained in:
siddontang 2015-02-08 09:30:54 +08:00
parent c2b3327130
commit dfa1fad4a1
2 changed files with 56 additions and 18 deletions

View File

@ -6,6 +6,7 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"sync" "sync"
"sync/atomic"
"time" "time"
) )
@ -31,35 +32,45 @@ const TimeFormat = "2006/01/02 15:04:05"
const maxBufPoolSize = 16 const maxBufPoolSize = 16
type Logger struct { type atomicInt32 int32
sync.Mutex
level int func (i *atomicInt32) Set(n int) {
atomic.StoreInt32((*int32)(i), int32(n))
}
func (i *atomicInt32) Get() int {
return int(atomic.LoadInt32((*int32)(i)))
}
type Logger struct {
level atomicInt32
flag int flag int
hMutex sync.Mutex
handler Handler handler Handler
quit chan struct{} quit chan struct{}
msg chan []byte msg chan []byte
bufMutex sync.Mutex
bufs [][]byte bufs [][]byte
wg sync.WaitGroup wg sync.WaitGroup
closed bool closed atomicInt32
} }
//new a logger with specified handler and flag //new a logger with specified handler and flag
func New(handler Handler, flag int) *Logger { func New(handler Handler, flag int) *Logger {
var l = new(Logger) var l = new(Logger)
l.level = LevelInfo l.level.Set(LevelInfo)
l.handler = handler l.handler = handler
l.flag = flag l.flag = flag
l.quit = make(chan struct{}) l.quit = make(chan struct{})
l.closed = false l.closed.Set(0)
l.msg = make(chan []byte, 1024) l.msg = make(chan []byte, 1024)
@ -88,7 +99,9 @@ func (l *Logger) run() {
for { for {
select { select {
case msg := <-l.msg: case msg := <-l.msg:
l.hMutex.Lock()
l.handler.Write(msg) l.handler.Write(msg)
l.hMutex.Unlock()
l.putBuf(msg) l.putBuf(msg)
case <-l.quit: case <-l.quit:
//we must log all msg //we must log all msg
@ -100,7 +113,7 @@ func (l *Logger) run() {
} }
func (l *Logger) popBuf() []byte { func (l *Logger) popBuf() []byte {
l.Lock() l.bufMutex.Lock()
var buf []byte var buf []byte
if len(l.bufs) == 0 { if len(l.bufs) == 0 {
buf = make([]byte, 0, 1024) buf = make([]byte, 0, 1024)
@ -108,25 +121,25 @@ func (l *Logger) popBuf() []byte {
buf = l.bufs[len(l.bufs)-1] buf = l.bufs[len(l.bufs)-1]
l.bufs = l.bufs[0 : len(l.bufs)-1] l.bufs = l.bufs[0 : len(l.bufs)-1]
} }
l.Unlock() l.bufMutex.Unlock()
return buf return buf
} }
func (l *Logger) putBuf(buf []byte) { func (l *Logger) putBuf(buf []byte) {
l.Lock() l.bufMutex.Lock()
if len(l.bufs) < maxBufPoolSize { if len(l.bufs) < maxBufPoolSize {
buf = buf[0:0] buf = buf[0:0]
l.bufs = append(l.bufs, buf) l.bufs = append(l.bufs, buf)
} }
l.Unlock() l.bufMutex.Unlock()
} }
func (l *Logger) Close() { func (l *Logger) Close() {
if l.closed { if l.closed.Get() == 1 {
return return
} }
l.closed = true l.closed.Set(1)
close(l.quit) close(l.quit)
@ -139,16 +152,30 @@ func (l *Logger) Close() {
//set log level, any log level less than it will not log //set log level, any log level less than it will not log
func (l *Logger) SetLevel(level int) { func (l *Logger) SetLevel(level int) {
l.level = level l.level.Set(level)
}
func (l *Logger) SetHandler(h Handler) {
if l.closed.Get() == 1 {
return
}
l.hMutex.Lock()
if l.handler != nil {
l.handler.Close()
}
l.handler = h
l.hMutex.Unlock()
} }
func (l *Logger) Output(callDepth int, level int, s string) { func (l *Logger) Output(callDepth int, level int, s string) {
if l.closed { if l.closed.Get() == 1 {
// closed // closed
return return
} }
if l.level > level { if l.level.Get() > level {
// higher level can be logged
return return
} }
@ -261,6 +288,10 @@ func SetLevel(level int) {
std.SetLevel(level) std.SetLevel(level)
} }
func SetHandler(h Handler) {
std.SetHandler(h)
}
func Trace(v ...interface{}) { func Trace(v ...interface{}) {
std.Output(2, LevelTrace, fmt.Sprint(v...)) std.Output(2, LevelTrace, fmt.Sprint(v...))
} }

View File

@ -16,7 +16,14 @@ func TestStdStreamLog(t *testing.T) {
Info("hello world") Info("hello world")
SetHandler(os.Stderr)
Infof("%s %d", "Hello", 123) Infof("%s %d", "Hello", 123)
SetLevel(LevelError)
Infof("%s %d", "Hello", 123)
Fatalf("%s %d", "Hello", 123)
} }
func TestRotatingFileLog(t *testing.T) { func TestRotatingFileLog(t *testing.T) {