...

Source file src/github.com/go-kit/log/sync.go

Documentation: github.com/go-kit/log

     1  package log
     2  
     3  import (
     4  	"io"
     5  	"sync"
     6  	"sync/atomic"
     7  )
     8  
     9  // SwapLogger wraps another logger that may be safely replaced while other
    10  // goroutines use the SwapLogger concurrently. The zero value for a SwapLogger
    11  // will discard all log events without error.
    12  //
    13  // SwapLogger serves well as a package global logger that can be changed by
    14  // importers.
    15  type SwapLogger struct {
    16  	logger atomic.Value
    17  }
    18  
    19  type loggerStruct struct {
    20  	Logger
    21  }
    22  
    23  // Log implements the Logger interface by forwarding keyvals to the currently
    24  // wrapped logger. It does not log anything if the wrapped logger is nil.
    25  func (l *SwapLogger) Log(keyvals ...interface{}) error {
    26  	s, ok := l.logger.Load().(loggerStruct)
    27  	if !ok || s.Logger == nil {
    28  		return nil
    29  	}
    30  	return s.Log(keyvals...)
    31  }
    32  
    33  // Swap replaces the currently wrapped logger with logger. Swap may be called
    34  // concurrently with calls to Log from other goroutines.
    35  func (l *SwapLogger) Swap(logger Logger) {
    36  	l.logger.Store(loggerStruct{logger})
    37  }
    38  
    39  // NewSyncWriter returns a new writer that is safe for concurrent use by
    40  // multiple goroutines. Writes to the returned writer are passed on to w. If
    41  // another write is already in progress, the calling goroutine blocks until
    42  // the writer is available.
    43  //
    44  // If w implements the following interface, so does the returned writer.
    45  //
    46  //    interface {
    47  //        Fd() uintptr
    48  //    }
    49  func NewSyncWriter(w io.Writer) io.Writer {
    50  	switch w := w.(type) {
    51  	case fdWriter:
    52  		return &fdSyncWriter{fdWriter: w}
    53  	default:
    54  		return &syncWriter{Writer: w}
    55  	}
    56  }
    57  
    58  // syncWriter synchronizes concurrent writes to an io.Writer.
    59  type syncWriter struct {
    60  	sync.Mutex
    61  	io.Writer
    62  }
    63  
    64  // Write writes p to the underlying io.Writer. If another write is already in
    65  // progress, the calling goroutine blocks until the syncWriter is available.
    66  func (w *syncWriter) Write(p []byte) (n int, err error) {
    67  	w.Lock()
    68  	defer w.Unlock()
    69  	return w.Writer.Write(p)
    70  }
    71  
    72  // fdWriter is an io.Writer that also has an Fd method. The most common
    73  // example of an fdWriter is an *os.File.
    74  type fdWriter interface {
    75  	io.Writer
    76  	Fd() uintptr
    77  }
    78  
    79  // fdSyncWriter synchronizes concurrent writes to an fdWriter.
    80  type fdSyncWriter struct {
    81  	sync.Mutex
    82  	fdWriter
    83  }
    84  
    85  // Write writes p to the underlying io.Writer. If another write is already in
    86  // progress, the calling goroutine blocks until the fdSyncWriter is available.
    87  func (w *fdSyncWriter) Write(p []byte) (n int, err error) {
    88  	w.Lock()
    89  	defer w.Unlock()
    90  	return w.fdWriter.Write(p)
    91  }
    92  
    93  // syncLogger provides concurrent safe logging for another Logger.
    94  type syncLogger struct {
    95  	mu     sync.Mutex
    96  	logger Logger
    97  }
    98  
    99  // NewSyncLogger returns a logger that synchronizes concurrent use of the
   100  // wrapped logger. When multiple goroutines use the SyncLogger concurrently
   101  // only one goroutine will be allowed to log to the wrapped logger at a time.
   102  // The other goroutines will block until the logger is available.
   103  func NewSyncLogger(logger Logger) Logger {
   104  	return &syncLogger{logger: logger}
   105  }
   106  
   107  // Log logs keyvals to the underlying Logger. If another log is already in
   108  // progress, the calling goroutine blocks until the syncLogger is available.
   109  func (l *syncLogger) Log(keyvals ...interface{}) error {
   110  	l.mu.Lock()
   111  	defer l.mu.Unlock()
   112  	return l.logger.Log(keyvals...)
   113  }
   114  

View as plain text