82 lines
1.8 KiB
Go
82 lines
1.8 KiB
Go
package logging
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sync"
|
|
)
|
|
|
|
/////////////////
|
|
// //
|
|
// SinkHandler //
|
|
// //
|
|
/////////////////
|
|
|
|
// SinkHandler sends log records to buffered channel, the logs are written in a dedicated routine consuming the channel.
|
|
type SinkHandler struct {
|
|
inner Handler
|
|
sinkCh chan *Record
|
|
bufSize int
|
|
wg sync.WaitGroup
|
|
}
|
|
|
|
// NewSinkHandler creates SinkHandler with sink channel buffer size bufSize that wraps inner handler for writing logs.
|
|
// When SinkHandler is created a go routine is started. When not used always call Close to terminate go routine.
|
|
func NewSinkHandler(inner Handler, bufSize int) *SinkHandler {
|
|
b := &SinkHandler{
|
|
inner: inner,
|
|
sinkCh: make(chan *Record, bufSize),
|
|
bufSize: bufSize,
|
|
}
|
|
|
|
b.wg.Add(1)
|
|
go b.process()
|
|
|
|
return b
|
|
}
|
|
|
|
// process reads log records from sinkCh and calls inner log handler to write it.
|
|
func (b *SinkHandler) process() {
|
|
for {
|
|
rec, ok := <-b.sinkCh
|
|
if !ok {
|
|
b.inner.Close()
|
|
break
|
|
}
|
|
|
|
b.inner.Handle(rec)
|
|
}
|
|
b.wg.Done()
|
|
}
|
|
|
|
// Status reports sink capacity and length.
|
|
func (b *SinkHandler) Status() (int, int) {
|
|
return b.bufSize, len(b.sinkCh)
|
|
}
|
|
|
|
// SetLevel sets logging level for handler
|
|
func (b *SinkHandler) SetLevel(l Level) {
|
|
b.inner.SetLevel(l)
|
|
}
|
|
|
|
// SetFormatter sets logging formatter for handler
|
|
func (b *SinkHandler) SetFormatter(f Formatter) {
|
|
b.inner.SetFormatter(f)
|
|
}
|
|
|
|
// Handle puts rec to the sink.
|
|
func (b *SinkHandler) Handle(rec *Record) {
|
|
select {
|
|
case b.sinkCh <- rec:
|
|
default:
|
|
fmt.Fprintf(os.Stderr, "SinkHandler buffer too small dropping record\n")
|
|
}
|
|
}
|
|
|
|
// Close closes the sink channel, inner handler will be closed when all pending logs are processed.
|
|
// Close blocks until all the logs are processed.
|
|
func (b *SinkHandler) Close() {
|
|
close(b.sinkCh)
|
|
b.wg.Wait()
|
|
}
|