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()
|
||
|
}
|