Skip to content

Commit

Permalink
✨ feat: update logger daemon flush logic, support stop control
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Jul 8, 2023
1 parent 37f31dd commit a60d020
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 14 deletions.
26 changes: 26 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package slog_test

import (
"fmt"
"sync"
"time"

"github.com/gookit/slog"
"github.com/gookit/slog/handler"
)
Expand Down Expand Up @@ -56,3 +60,25 @@ func ExampleNew() {
mylog.Warn("warning log message")
mylog.Infof("info log %s", "message")
}

func ExampleFlushDaemon() {
wg := sync.WaitGroup{}
wg.Add(1)

go slog.FlushDaemon(func() {
fmt.Println("flush daemon stopped")
wg.Done()
})

go func() {
// mock app running
time.Sleep(time.Second * 2)

// stop daemon
fmt.Println("stop flush daemon")
slog.StopDaemon()
}()

// wait for stop
wg.Wait()
}
44 changes: 36 additions & 8 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ type Logger struct {
recordPool sync.Pool
// handlers on exit.
exitHandlers []func()
quitDaemon chan struct{}

//
// logger options
//

// ChannelName log channel name, default is DefaultChannelName
ChannelName string
// FlushInterval flush interval time. default is defaultFlushInterval=30s
FlushInterval time.Duration
// LowerLevelName use lower level name
LowerLevelName bool
// ReportCaller on write log record
Expand Down Expand Up @@ -76,6 +79,8 @@ func NewWithName(name string, fns ...LoggerFn) *Logger {
ReportCaller: true,
CallerSkip: 6,
TimeClock: DefaultClockFn,
// flush interval time
FlushInterval: defaultFlushInterval,
}

logger.recordPool.New = func() any {
Expand Down Expand Up @@ -149,21 +154,44 @@ func (l *Logger) Name() string { return l.name }
// ---------------------------------------------------------------------------
//

const flushInterval = 30 * time.Second
const defaultFlushInterval = 30 * time.Second

// FlushDaemon run flush handle on daemon
//
// Usage:
//
// go slog.FlushDaemon()
func (l *Logger) FlushDaemon() {
for range time.NewTicker(flushInterval).C {
if err := l.lockAndFlushAll(); err != nil {
printlnStderr("slog.FlushDaemon: daemon flush logs error: ", err)
// Usage please refer to the FlushDaemon() on package.
func (l *Logger) FlushDaemon(onStops ...func()) {
l.quitDaemon = make(chan struct{})
if l.FlushInterval <= 0 {
l.FlushInterval = defaultFlushInterval
}

// create a ticker
tk := time.NewTicker(l.FlushInterval)
defer tk.Stop()

for {
select {
case <-tk.C:
if err := l.lockAndFlushAll(); err != nil {
printlnStderr("slog.FlushDaemon: daemon flush logs error: ", err)
}
case <-l.quitDaemon:
for _, fn := range onStops {
fn()
}
return
}
}
}

// StopDaemon stop flush daemon
func (l *Logger) StopDaemon() {
if l.quitDaemon == nil {
panic("cannot quit daemon, please call FlushDaemon() first")
}
close(l.quitDaemon)
}

// FlushTimeout flush logs on limit time.
//
// refer from glog package
Expand Down
15 changes: 9 additions & 6 deletions slog.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,17 @@ func MustFlush() { goutil.PanicErr(Flush()) }
// FlushTimeout flush logs with timeout.
func FlushTimeout(timeout time.Duration) { std.FlushTimeout(timeout) }

// FlushDaemon run flush handle on daemon
// FlushDaemon run flush handle on daemon.
//
// Usage:
//
// go slog.FlushDaemon()
func FlushDaemon() { std.FlushDaemon() }
// Usage please see ExampleFlushDaemon()
func FlushDaemon(onStops ...func()) {
std.FlushDaemon(onStops...)
}

// StopDaemon stop flush daemon
func StopDaemon() { std.StopDaemon() }

// SetLogLevel for the std logger
// SetLogLevel max level for the std logger
func SetLogLevel(l Level) { std.Level = l }

// SetFormatter to std logger
Expand Down
35 changes: 35 additions & 0 deletions slog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"errors"
"fmt"
"strconv"
"sync"
"testing"
"time"

"github.com/gookit/goutil/byteutil"
"github.com/gookit/goutil/errorx"
Expand Down Expand Up @@ -64,6 +66,39 @@ func TestTextFormatNoColor(t *testing.T) {

func TestFlushDaemon(t *testing.T) {
defer slog.Reset()

buf := byteutil.NewBuffer()
slog.Configure(func(l *slog.SugaredLogger) {
l.FlushInterval = timex.Millisecond * 100
l.Output = buf
})

wg := sync.WaitGroup{}
wg.Add(1)

go slog.FlushDaemon(func() {
fmt.Println("flush daemon stopped")
wg.Done()
})

go func() {
// mock app running
time.Sleep(time.Second * 1)

// stop daemon
fmt.Println("stop flush daemon")
slog.StopDaemon()
}()

slog.Info("print log message")

wg.Wait()

fmt.Print(buf.ResetGet())
}

func TestFlushTimeout(t *testing.T) {
defer slog.Reset()
slog.Info("print log message")
slog.FlushTimeout(timex.Second * 1)
}
Expand Down

0 comments on commit a60d020

Please sign in to comment.