github.com/kinvolk/docker@v1.13.1/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 piece of output produced by some
    30  // container.  The Line member is a slice of an array whose contents can be
    31  // changed after a log driver's Log() method returns.
    32  type Message struct {
    33  	Line      []byte
    34  	Source    string
    35  	Timestamp time.Time
    36  	Attrs     LogAttributes
    37  	Partial   bool
    38  }
    39  
    40  // CopyMessage creates a copy of the passed-in Message which will remain
    41  // unchanged if the original is changed.  Log drivers which buffer Messages
    42  // rather than dispatching them during their Log() method should use this
    43  // function to obtain a Message whose Line member's contents won't change.
    44  func CopyMessage(msg *Message) *Message {
    45  	m := new(Message)
    46  	m.Line = make([]byte, len(msg.Line))
    47  	copy(m.Line, msg.Line)
    48  	m.Source = msg.Source
    49  	m.Timestamp = msg.Timestamp
    50  	m.Partial = msg.Partial
    51  	m.Attrs = make(LogAttributes)
    52  	for k, v := range msg.Attrs {
    53  		m.Attrs[k] = v
    54  	}
    55  	return m
    56  }
    57  
    58  // LogAttributes is used to hold the extra attributes available in the log message
    59  // Primarily used for converting the map type to string and sorting.
    60  type LogAttributes map[string]string
    61  type byKey []string
    62  
    63  func (s byKey) Len() int { return len(s) }
    64  func (s byKey) Less(i, j int) bool {
    65  	keyI := strings.Split(s[i], "=")
    66  	keyJ := strings.Split(s[j], "=")
    67  	return keyI[0] < keyJ[0]
    68  }
    69  func (s byKey) Swap(i, j int) {
    70  	s[i], s[j] = s[j], s[i]
    71  }
    72  
    73  func (a LogAttributes) String() string {
    74  	var ss byKey
    75  	for k, v := range a {
    76  		ss = append(ss, k+"="+v)
    77  	}
    78  	sort.Sort(ss)
    79  	return strings.Join(ss, ",")
    80  }
    81  
    82  // Logger is the interface for docker logging drivers.
    83  type Logger interface {
    84  	Log(*Message) error
    85  	Name() string
    86  	Close() error
    87  }
    88  
    89  // ReadConfig is the configuration passed into ReadLogs.
    90  type ReadConfig struct {
    91  	Since  time.Time
    92  	Tail   int
    93  	Follow bool
    94  }
    95  
    96  // LogReader is the interface for reading log messages for loggers that support reading.
    97  type LogReader interface {
    98  	// Read logs from underlying logging backend
    99  	ReadLogs(ReadConfig) *LogWatcher
   100  }
   101  
   102  // LogWatcher is used when consuming logs read from the LogReader interface.
   103  type LogWatcher struct {
   104  	// For sending log messages to a reader.
   105  	Msg chan *Message
   106  	// For sending error messages that occur while while reading logs.
   107  	Err           chan error
   108  	closeOnce     sync.Once
   109  	closeNotifier chan struct{}
   110  }
   111  
   112  // NewLogWatcher returns a new LogWatcher.
   113  func NewLogWatcher() *LogWatcher {
   114  	return &LogWatcher{
   115  		Msg:           make(chan *Message, logWatcherBufferSize),
   116  		Err:           make(chan error, 1),
   117  		closeNotifier: make(chan struct{}),
   118  	}
   119  }
   120  
   121  // Close notifies the underlying log reader to stop.
   122  func (w *LogWatcher) Close() {
   123  	// only close if not already closed
   124  	w.closeOnce.Do(func() {
   125  		close(w.closeNotifier)
   126  	})
   127  }
   128  
   129  // WatchClose returns a channel receiver that receives notification
   130  // when the watcher has been closed. This should only be called from
   131  // one goroutine.
   132  func (w *LogWatcher) WatchClose() <-chan struct{} {
   133  	return w.closeNotifier
   134  }