github.com/LazyboyChen7/engine@v17.12.1-ce-rc2+incompatible/daemon/logger/adapter.go (about)

     1  package logger
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"strings"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/docker/docker/api/types/plugins/logdriver"
    11  	"github.com/docker/docker/pkg/plugingetter"
    12  	"github.com/pkg/errors"
    13  	"github.com/sirupsen/logrus"
    14  )
    15  
    16  // pluginAdapter takes a plugin and implements the Logger interface for logger
    17  // instances
    18  type pluginAdapter struct {
    19  	driverName   string
    20  	id           string
    21  	plugin       logPlugin
    22  	basePath     string
    23  	fifoPath     string
    24  	capabilities Capability
    25  	logInfo      Info
    26  
    27  	// synchronize access to the log stream and shared buffer
    28  	mu     sync.Mutex
    29  	enc    logdriver.LogEntryEncoder
    30  	stream io.WriteCloser
    31  	// buf is shared for each `Log()` call to reduce allocations.
    32  	// buf must be protected by mutex
    33  	buf logdriver.LogEntry
    34  }
    35  
    36  func (a *pluginAdapter) Log(msg *Message) error {
    37  	a.mu.Lock()
    38  
    39  	a.buf.Line = msg.Line
    40  	a.buf.TimeNano = msg.Timestamp.UnixNano()
    41  	a.buf.Partial = msg.Partial
    42  	a.buf.Source = msg.Source
    43  
    44  	err := a.enc.Encode(&a.buf)
    45  	a.buf.Reset()
    46  
    47  	a.mu.Unlock()
    48  
    49  	PutMessage(msg)
    50  	return err
    51  }
    52  
    53  func (a *pluginAdapter) Name() string {
    54  	return a.driverName
    55  }
    56  
    57  func (a *pluginAdapter) Close() error {
    58  	a.mu.Lock()
    59  	defer a.mu.Unlock()
    60  
    61  	if err := a.plugin.StopLogging(strings.TrimPrefix(a.fifoPath, a.basePath)); err != nil {
    62  		return err
    63  	}
    64  
    65  	if err := a.stream.Close(); err != nil {
    66  		logrus.WithError(err).Error("error closing plugin fifo")
    67  	}
    68  	if err := os.Remove(a.fifoPath); err != nil && !os.IsNotExist(err) {
    69  		logrus.WithError(err).Error("error cleaning up plugin fifo")
    70  	}
    71  
    72  	// may be nil, especially for unit tests
    73  	if pluginGetter != nil {
    74  		pluginGetter.Get(a.Name(), extName, plugingetter.Release)
    75  	}
    76  	return nil
    77  }
    78  
    79  type pluginAdapterWithRead struct {
    80  	*pluginAdapter
    81  }
    82  
    83  func (a *pluginAdapterWithRead) ReadLogs(config ReadConfig) *LogWatcher {
    84  	watcher := NewLogWatcher()
    85  
    86  	go func() {
    87  		defer close(watcher.Msg)
    88  		stream, err := a.plugin.ReadLogs(a.logInfo, config)
    89  		if err != nil {
    90  			watcher.Err <- errors.Wrap(err, "error getting log reader")
    91  			return
    92  		}
    93  		defer stream.Close()
    94  
    95  		dec := logdriver.NewLogEntryDecoder(stream)
    96  		for {
    97  			select {
    98  			case <-watcher.WatchClose():
    99  				return
   100  			default:
   101  			}
   102  
   103  			var buf logdriver.LogEntry
   104  			if err := dec.Decode(&buf); err != nil {
   105  				if err == io.EOF {
   106  					return
   107  				}
   108  				select {
   109  				case watcher.Err <- errors.Wrap(err, "error decoding log message"):
   110  				case <-watcher.WatchClose():
   111  				}
   112  				return
   113  			}
   114  
   115  			msg := &Message{
   116  				Timestamp: time.Unix(0, buf.TimeNano),
   117  				Line:      buf.Line,
   118  				Source:    buf.Source,
   119  			}
   120  
   121  			// plugin should handle this, but check just in case
   122  			if !config.Since.IsZero() && msg.Timestamp.Before(config.Since) {
   123  				continue
   124  			}
   125  			if !config.Until.IsZero() && msg.Timestamp.After(config.Until) {
   126  				return
   127  			}
   128  
   129  			select {
   130  			case watcher.Msg <- msg:
   131  			case <-watcher.WatchClose():
   132  				// make sure the message we consumed is sent
   133  				watcher.Msg <- msg
   134  				return
   135  			}
   136  		}
   137  	}()
   138  
   139  	return watcher
   140  }