github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/logging/loggers/capture_logger.go (about) 1 package loggers 2 3 import ( 4 "sync" 5 6 "github.com/eapache/channels" 7 "github.com/go-kit/kit/log" 8 "github.com/hyperledger/burrow/logging/structure" 9 ) 10 11 type CaptureLogger struct { 12 bufferLogger *ChannelLogger 13 outputLogger log.Logger 14 passthrough bool 15 sync.RWMutex 16 } 17 18 var _ log.Logger = (*CaptureLogger)(nil) 19 20 // Capture logger captures output sent to it in a buffer retaining 21 // a reference to its output logger (the logger whose input it is capturing). 22 // It can optionally pass logs through to the output logger. 23 // Because it holds a reference to its output it can also be used to coordinate 24 // Flushing of the buffer to the output logger in special circumstances. 25 func NewCaptureLogger(outputLogger log.Logger, bufferCap channels.BufferCap, passthrough bool) *CaptureLogger { 26 return &CaptureLogger{ 27 bufferLogger: NewChannelLogger(bufferCap), 28 outputLogger: outputLogger, 29 passthrough: passthrough, 30 } 31 } 32 33 func (cl *CaptureLogger) Log(keyvals ...interface{}) error { 34 switch structure.Signal(keyvals) { 35 case structure.SyncSignal: 36 err := cl.Flush() 37 if err != nil { 38 return err 39 } 40 // Pass the signal along 41 return cl.outputLogger.Log(keyvals...) 42 } 43 err := cl.bufferLogger.Log(keyvals...) 44 if err != nil { 45 return err 46 } 47 if cl.Passthrough() { 48 err = cl.outputLogger.Log(keyvals...) 49 if err != nil { 50 return err 51 } 52 } 53 return nil 54 } 55 56 // Sets whether the CaptureLogger is forwarding log lines sent to it through 57 // to its output logger. Concurrently safe. 58 func (cl *CaptureLogger) SetPassthrough(passthrough bool) { 59 cl.Lock() 60 defer cl.Unlock() 61 cl.passthrough = passthrough 62 } 63 64 // Gets whether the CaptureLogger is forwarding log lines sent to through to its 65 // OutputLogger. Concurrently Safe. 66 func (cl *CaptureLogger) Passthrough() bool { 67 cl.RLock() 68 defer cl.RUnlock() 69 return cl.passthrough 70 } 71 72 // Flushes every log line available in the buffer at the time of calling 73 // to the OutputLogger and returns. Does not block indefinitely. 74 // 75 // Note: will remove log lines from buffer so they will not be produced on any 76 // subsequent flush of buffer 77 func (cl *CaptureLogger) Flush() error { 78 return cl.bufferLogger.Flush(cl.outputLogger) 79 } 80 81 // Flushes every log line available in the buffer at the time of calling 82 // to a slice and returns it. Does not block indefinitely. 83 // 84 // Note: will remove log lines from buffer so they will not be produced on any 85 // subsequent flush of buffer 86 func (cl *CaptureLogger) FlushLogLines() [][]interface{} { 87 return cl.bufferLogger.FlushLogLines() 88 } 89 90 // The OutputLogger whose input this CaptureLogger is capturing 91 func (cl *CaptureLogger) OutputLogger() log.Logger { 92 return cl.outputLogger 93 } 94 95 // The BufferLogger where the input into these CaptureLogger is stored in a ring 96 // buffer of log lines. 97 func (cl *CaptureLogger) BufferLogger() *ChannelLogger { 98 return cl.bufferLogger 99 }