mlog: use a Clone and Set methods instead of With methods
This commit is contained in:
parent
910704ae67
commit
5c85969bc7
69
mlog/mlog.go
69
mlog/mlog.go
@ -244,7 +244,9 @@ type msg struct {
|
|||||||
// Logger wraps a WriteFn and an io.WriteCloser such that logging calls on the
|
// Logger wraps a WriteFn and an io.WriteCloser such that logging calls on the
|
||||||
// Logger will use them (in a thread-safe manner) to write out log messages.
|
// Logger will use them (in a thread-safe manner) to write out log messages.
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
wc io.WriteCloser
|
wc io.WriteCloser
|
||||||
|
|
||||||
|
l *sync.RWMutex
|
||||||
wfn WriteFn
|
wfn WriteFn
|
||||||
maxLevel uint
|
maxLevel uint
|
||||||
kv KVer
|
kv KVer
|
||||||
@ -261,17 +263,18 @@ type Logger struct {
|
|||||||
// to the given WriteCloser.
|
// to the given WriteCloser.
|
||||||
func NewLogger(wc io.WriteCloser) *Logger {
|
func NewLogger(wc io.WriteCloser) *Logger {
|
||||||
l := &Logger{
|
l := &Logger{
|
||||||
wc: wc,
|
wc: wc,
|
||||||
wfn: DefaultWriteFn,
|
l: new(sync.RWMutex),
|
||||||
|
wfn: DefaultWriteFn,
|
||||||
|
maxLevel: InfoLevel.Uint(),
|
||||||
msgBufPool: &sync.Pool{
|
msgBufPool: &sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
return new(bytes.Buffer)
|
return new(bytes.Buffer)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
msgCh: make(chan msg, 1024),
|
msgCh: make(chan msg, 1024),
|
||||||
maxLevel: InfoLevel.Uint(),
|
stopCh: make(chan struct{}),
|
||||||
stopCh: make(chan struct{}),
|
wg: new(sync.WaitGroup),
|
||||||
wg: new(sync.WaitGroup),
|
|
||||||
}
|
}
|
||||||
l.wg.Add(1)
|
l.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -281,8 +284,13 @@ func NewLogger(wc io.WriteCloser) *Logger {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) cp() *Logger {
|
// Clone returns a usable copy of the *Logger. Changes to the returned Logger
|
||||||
|
// will not effect the original, e.g. if the SetMaxLevel is called on one it
|
||||||
|
// will not effect the max level of written logs on the other. If Stop is called
|
||||||
|
// on any Logger it effects all parent and child Loggers produced from Clone.
|
||||||
|
func (l *Logger) Clone() *Logger {
|
||||||
l2 := *l
|
l2 := *l
|
||||||
|
l2.l = new(sync.RWMutex)
|
||||||
return &l2
|
return &l2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,37 +332,35 @@ func (l *Logger) spin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithMaxLevelUint returns a copy of the Logger with its max logging level set
|
// SetMaxLevelUint sets the Logger's max logging level so that it will not log
|
||||||
// to the given uint. The Logger will not log any messages with a higher
|
// any messages with a higher Level.Uint value.
|
||||||
// Level.Uint value.
|
func (l *Logger) SetMaxLevelUint(i uint) {
|
||||||
func (l *Logger) WithMaxLevelUint(i uint) *Logger {
|
l.l.Lock()
|
||||||
l = l.cp()
|
defer l.l.Unlock()
|
||||||
l.maxLevel = i
|
l.maxLevel = i
|
||||||
return l
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithMaxLevel returns a copy of the Logger with its max Level set to the given
|
// SetMaxLevel sets the Logger's max logging level so that it will not log any
|
||||||
// one. The Logger will not log any messages with a higher Level.Uint value.
|
// messages with a higher Level.Uint value.
|
||||||
func (l *Logger) WithMaxLevel(lvl Level) *Logger {
|
func (l *Logger) SetMaxLevel(lvl Level) {
|
||||||
return l.WithMaxLevelUint(lvl.Uint())
|
l.SetMaxLevelUint(lvl.Uint())
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithWriteFn returns a copy of the Logger which will use the given WriteFn
|
// SetWriteFn sets the Logger to use the given WriteFn to format and write
|
||||||
// to format and write Messages to the Logger's WriteCloser. This does not
|
// Messages to Logger's WriteCloser.
|
||||||
// affect the WriteFn of the original Logger, and both can be used at the same
|
func (l *Logger) SetWriteFn(wfn WriteFn) {
|
||||||
// time.
|
l.l.Lock()
|
||||||
func (l *Logger) WithWriteFn(wfn WriteFn) *Logger {
|
defer l.l.Unlock()
|
||||||
l = l.cp()
|
|
||||||
l.wfn = wfn
|
l.wfn = wfn
|
||||||
return l
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithKV returns a copy of Logger which will implicitly use the KVers for all
|
// AddKV sets the Logger to implicitly add the given KVers to all log messages.
|
||||||
// log messages.
|
// This will not affect KVer data previously added the Logger or its parent (see
|
||||||
func (l *Logger) WithKV(kvs ...KVer) *Logger {
|
// Clone), except to overwrite keys in the case of overlap.
|
||||||
l = l.cp()
|
func (l *Logger) AddKV(kvs ...KVer) {
|
||||||
|
l.l.Lock()
|
||||||
|
defer l.l.Unlock()
|
||||||
l.kv = MergeInto(l.kv, kvs...)
|
l.kv = MergeInto(l.kv, kvs...)
|
||||||
return l
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops and cleans up any running go-routines and resources held by the
|
// Stop stops and cleans up any running go-routines and resources held by the
|
||||||
@ -371,6 +377,9 @@ func (l *Logger) Stop() {
|
|||||||
// will be Merge'd automatically. If the Level is a fatal (Uint() == 0) then
|
// will be Merge'd automatically. If the Level is a fatal (Uint() == 0) then
|
||||||
// calling this will never return, and the process will have os.Exit(1) called.
|
// calling this will never return, and the process will have os.Exit(1) called.
|
||||||
func (l *Logger) Log(lvl Level, msgStr string, kvs ...KVer) {
|
func (l *Logger) Log(lvl Level, msgStr string, kvs ...KVer) {
|
||||||
|
l.l.RLock()
|
||||||
|
defer l.l.RUnlock()
|
||||||
|
|
||||||
if l.maxLevel < lvl.Uint() {
|
if l.maxLevel < lvl.Uint() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func TestLogger(t *T) {
|
|||||||
select {
|
select {
|
||||||
case <-l.testMsgWrittenCh:
|
case <-l.testMsgWrittenCh:
|
||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1 * time.Second):
|
||||||
t.Fatal("waited too long for msg to write")
|
return massert.Errf("waited too long for msg to write")
|
||||||
}
|
}
|
||||||
out, err := buf.ReadString('\n')
|
out, err := buf.ReadString('\n')
|
||||||
return massert.All(
|
return massert.All(
|
||||||
@ -82,32 +82,30 @@ func TestLogger(t *T) {
|
|||||||
assertOut("~ ERROR -- buz\n"),
|
assertOut("~ ERROR -- buz\n"),
|
||||||
))
|
))
|
||||||
|
|
||||||
{
|
l.SetMaxLevel(WarnLevel)
|
||||||
l := l.WithMaxLevel(WarnLevel)
|
l.Log(DebugLevel, "foo")
|
||||||
l.Log(DebugLevel, "foo")
|
l.Log(InfoLevel, "bar")
|
||||||
l.Log(InfoLevel, "bar")
|
l.Log(WarnLevel, "baz")
|
||||||
l.Log(WarnLevel, "baz")
|
l.Log(ErrorLevel, "buz", KV{"a": "b"})
|
||||||
l.Log(ErrorLevel, "buz", KV{"a": "b"})
|
massert.Fatal(t, massert.All(
|
||||||
massert.Fatal(t, massert.All(
|
assertOut("~ WARN -- baz\n"),
|
||||||
assertOut("~ WARN -- baz\n"),
|
assertOut("~ ERROR -- buz -- a=\"b\"\n"),
|
||||||
assertOut("~ ERROR -- buz -- a=\"b\"\n"),
|
))
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
l2 := l.Clone()
|
||||||
l2 := l.WithWriteFn(func(w io.Writer, msg Message) error {
|
l2.SetMaxLevel(InfoLevel)
|
||||||
msg.Msg = strings.ToUpper(msg.Msg)
|
l2.SetWriteFn(func(w io.Writer, msg Message) error {
|
||||||
return DefaultWriteFn(w, msg)
|
msg.Msg = strings.ToUpper(msg.Msg)
|
||||||
})
|
return DefaultWriteFn(w, msg)
|
||||||
l2.Log(InfoLevel, "bar")
|
})
|
||||||
l2.Log(WarnLevel, "baz")
|
l2.Log(InfoLevel, "bar")
|
||||||
l.Log(ErrorLevel, "buz")
|
l2.Log(WarnLevel, "baz")
|
||||||
massert.Fatal(t, massert.All(
|
l.Log(ErrorLevel, "buz")
|
||||||
assertOut("~ INFO -- BAR\n"),
|
massert.Fatal(t, massert.All(
|
||||||
assertOut("~ WARN -- BAZ\n"),
|
assertOut("~ INFO -- BAR\n"),
|
||||||
assertOut("~ ERROR -- buz\n"),
|
assertOut("~ WARN -- BAZ\n"),
|
||||||
))
|
assertOut("~ ERROR -- buz\n"),
|
||||||
}
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultWriteFn(t *T) {
|
func TestDefaultWriteFn(t *T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user