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