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  }