github.com/dpiddy/docker@v1.12.2-rc1/daemon/logger/logger.go (about)

     1  // Package logger defines interfaces that logger drivers implement to
     2  // log messages.
     3  //
     4  // The other half of a logger driver is the implementation of the
     5  // factory, which holds the contextual instance information that
     6  // allows multiple loggers of the same type to perform different
     7  // actions, such as logging to different locations.
     8  package logger
     9  
    10  import (
    11  	"errors"
    12  	"sort"
    13  	"strings"
    14  	"sync"
    15  	"time"
    16  
    17  	"github.com/docker/docker/pkg/jsonlog"
    18  )
    19  
    20  // ErrReadLogsNotSupported is returned when the logger does not support reading logs.
    21  var ErrReadLogsNotSupported = errors.New("configured logging reader does not support reading")
    22  
    23  const (
    24  	// TimeFormat is the time format used for timestamps sent to log readers.
    25  	TimeFormat           = jsonlog.RFC3339NanoFixed
    26  	logWatcherBufferSize = 4096
    27  )
    28  
    29  // Message is datastructure that represents record from some container.
    30  type Message struct {
    31  	Line      []byte
    32  	Source    string
    33  	Timestamp time.Time
    34  	Attrs     LogAttributes
    35  }
    36  
    37  // LogAttributes is used to hold the extra attributes available in the log message
    38  // Primarily used for converting the map type to string and sorting.
    39  type LogAttributes map[string]string
    40  type byKey []string
    41  
    42  func (s byKey) Len() int { return len(s) }
    43  func (s byKey) Less(i, j int) bool {
    44  	keyI := strings.Split(s[i], "=")
    45  	keyJ := strings.Split(s[j], "=")
    46  	return keyI[0] < keyJ[0]
    47  }
    48  func (s byKey) Swap(i, j int) {
    49  	s[i], s[j] = s[j], s[i]
    50  }
    51  
    52  func (a LogAttributes) String() string {
    53  	var ss byKey
    54  	for k, v := range a {
    55  		ss = append(ss, k+"="+v)
    56  	}
    57  	sort.Sort(ss)
    58  	return strings.Join(ss, ",")
    59  }
    60  
    61  // Logger is the interface for docker logging drivers.
    62  type Logger interface {
    63  	Log(*Message) error
    64  	Name() string
    65  	Close() error
    66  }
    67  
    68  // ReadConfig is the configuration passed into ReadLogs.
    69  type ReadConfig struct {
    70  	Since  time.Time
    71  	Tail   int
    72  	Follow bool
    73  }
    74  
    75  // LogReader is the interface for reading log messages for loggers that support reading.
    76  type LogReader interface {
    77  	// Read logs from underlying logging backend
    78  	ReadLogs(ReadConfig) *LogWatcher
    79  }
    80  
    81  // LogWatcher is used when consuming logs read from the LogReader interface.
    82  type LogWatcher struct {
    83  	// For sending log messages to a reader.
    84  	Msg chan *Message
    85  	// For sending error messages that occur while while reading logs.
    86  	Err           chan error
    87  	closeOnce     sync.Once
    88  	closeNotifier chan struct{}
    89  }
    90  
    91  // NewLogWatcher returns a new LogWatcher.
    92  func NewLogWatcher() *LogWatcher {
    93  	return &LogWatcher{
    94  		Msg:           make(chan *Message, logWatcherBufferSize),
    95  		Err:           make(chan error, 1),
    96  		closeNotifier: make(chan struct{}),
    97  	}
    98  }
    99  
   100  // Close notifies the underlying log reader to stop.
   101  func (w *LogWatcher) Close() {
   102  	// only close if not already closed
   103  	w.closeOnce.Do(func() {
   104  		close(w.closeNotifier)
   105  	})
   106  }
   107  
   108  // WatchClose returns a channel receiver that receives notification
   109  // when the watcher has been closed. This should only be called from
   110  // one goroutine.
   111  func (w *LogWatcher) WatchClose() <-chan struct{} {
   112  	return w.closeNotifier
   113  }