345d1fd089
Signed-off-by: Bily Zhang <xcoder@tenxcloud.com>
162 lines
4.8 KiB
Go
162 lines
4.8 KiB
Go
// Package logger defines interfaces that logger drivers implement to
|
|
// log messages.
|
|
//
|
|
// The other half of a logger driver is the implementation of the
|
|
// factory, which holds the contextual instance information that
|
|
// allows multiple loggers of the same type to perform different
|
|
// actions, such as logging to different locations.
|
|
package logger // import "github.com/docker/docker/daemon/logger"
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/docker/docker/api/types/backend"
|
|
)
|
|
|
|
// ErrReadLogsNotSupported is returned when the underlying log driver does not support reading
|
|
type ErrReadLogsNotSupported struct{}
|
|
|
|
func (ErrReadLogsNotSupported) Error() string {
|
|
return "configured logging driver does not support reading"
|
|
}
|
|
|
|
// NotImplemented makes this error implement the `NotImplemented` interface from api/errdefs
|
|
func (ErrReadLogsNotSupported) NotImplemented() {}
|
|
|
|
const (
|
|
logWatcherBufferSize = 4096
|
|
)
|
|
|
|
var messagePool = &sync.Pool{New: func() interface{} { return &Message{Line: make([]byte, 0, 256)} }}
|
|
|
|
// NewMessage returns a new message from the message sync.Pool
|
|
func NewMessage() *Message {
|
|
return messagePool.Get().(*Message)
|
|
}
|
|
|
|
// PutMessage puts the specified message back n the message pool.
|
|
// The message fields are reset before putting into the pool.
|
|
func PutMessage(msg *Message) {
|
|
msg.reset()
|
|
messagePool.Put(msg)
|
|
}
|
|
|
|
// Message is data structure that represents piece of output produced by some
|
|
// container. The Line member is a slice of an array whose contents can be
|
|
// changed after a log driver's Log() method returns.
|
|
//
|
|
// Message is subtyped from backend.LogMessage because there is a lot of
|
|
// internal complexity around the Message type that should not be exposed
|
|
// to any package not explicitly importing the logger type.
|
|
//
|
|
// Any changes made to this struct must also be updated in the `reset` function
|
|
type Message backend.LogMessage
|
|
|
|
// reset sets the message back to default values
|
|
// This is used when putting a message back into the message pool.
|
|
// Any changes to the `Message` struct should be reflected here.
|
|
func (m *Message) reset() {
|
|
m.Line = m.Line[:0]
|
|
m.Source = ""
|
|
m.Attrs = nil
|
|
m.PLogMetaData = nil
|
|
|
|
m.Err = nil
|
|
}
|
|
|
|
// AsLogMessage returns a pointer to the message as a pointer to
|
|
// backend.LogMessage, which is an identical type with a different purpose
|
|
func (m *Message) AsLogMessage() *backend.LogMessage {
|
|
return (*backend.LogMessage)(m)
|
|
}
|
|
|
|
// Logger is the interface for docker logging drivers.
|
|
type Logger interface {
|
|
Log(*Message) error
|
|
Name() string
|
|
Close() error
|
|
}
|
|
|
|
// SizedLogger is the interface for logging drivers that can control
|
|
// the size of buffer used for their messages.
|
|
type SizedLogger interface {
|
|
Logger
|
|
BufSize() int
|
|
}
|
|
|
|
// ReadConfig is the configuration passed into ReadLogs.
|
|
type ReadConfig struct {
|
|
Since time.Time
|
|
Until time.Time
|
|
Tail int
|
|
Follow bool
|
|
}
|
|
|
|
// LogReader is the interface for reading log messages for loggers that support reading.
|
|
type LogReader interface {
|
|
// Read logs from underlying logging backend
|
|
ReadLogs(ReadConfig) *LogWatcher
|
|
}
|
|
|
|
// LogWatcher is used when consuming logs read from the LogReader interface.
|
|
type LogWatcher struct {
|
|
// For sending log messages to a reader.
|
|
Msg chan *Message
|
|
// For sending error messages that occur while reading logs.
|
|
Err chan error
|
|
producerOnce sync.Once
|
|
producerGone chan struct{}
|
|
consumerOnce sync.Once
|
|
consumerGone chan struct{}
|
|
}
|
|
|
|
// NewLogWatcher returns a new LogWatcher.
|
|
func NewLogWatcher() *LogWatcher {
|
|
return &LogWatcher{
|
|
Msg: make(chan *Message, logWatcherBufferSize),
|
|
Err: make(chan error, 1),
|
|
producerGone: make(chan struct{}),
|
|
consumerGone: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
// ProducerGone notifies the underlying log reader that
|
|
// the logs producer (a container) is gone.
|
|
func (w *LogWatcher) ProducerGone() {
|
|
// only close if not already closed
|
|
w.producerOnce.Do(func() {
|
|
close(w.producerGone)
|
|
})
|
|
}
|
|
|
|
// WatchProducerGone returns a channel receiver that receives notification
|
|
// once the logs producer (a container) is gone.
|
|
func (w *LogWatcher) WatchProducerGone() <-chan struct{} {
|
|
return w.producerGone
|
|
}
|
|
|
|
// ConsumerGone notifies that the logs consumer is gone.
|
|
func (w *LogWatcher) ConsumerGone() {
|
|
// only close if not already closed
|
|
w.consumerOnce.Do(func() {
|
|
close(w.consumerGone)
|
|
})
|
|
}
|
|
|
|
// WatchConsumerGone returns a channel receiver that receives notification
|
|
// when the log watcher consumer is gone.
|
|
func (w *LogWatcher) WatchConsumerGone() <-chan struct{} {
|
|
return w.consumerGone
|
|
}
|
|
|
|
// Capability defines the list of capabilities that a driver can implement
|
|
// These capabilities are not required to be a logging driver, however do
|
|
// determine how a logging driver can be used
|
|
type Capability struct {
|
|
// Determines if a log driver can read back logs
|
|
ReadLogs bool
|
|
}
|
|
|
|
// MarshalFunc is a func that marshals a message into an arbitrary format
|
|
type MarshalFunc func(*Message) ([]byte, error)
|