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

     1  package jsonfilelog
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  
     7  	"github.com/docker/docker/api/types/backend"
     8  	"github.com/docker/docker/daemon/logger"
     9  	"github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog"
    10  )
    11  
    12  const maxJSONDecodeRetry = 20000
    13  
    14  // ReadLogs implements the logger's LogReader interface for the logs
    15  // created by this driver.
    16  func (l *JSONFileLogger) ReadLogs(config logger.ReadConfig) *logger.LogWatcher {
    17  	logWatcher := logger.NewLogWatcher()
    18  
    19  	go l.readLogs(logWatcher, config)
    20  	return logWatcher
    21  }
    22  
    23  func (l *JSONFileLogger) readLogs(watcher *logger.LogWatcher, config logger.ReadConfig) {
    24  	defer close(watcher.Msg)
    25  
    26  	l.mu.Lock()
    27  	l.readers[watcher] = struct{}{}
    28  	l.mu.Unlock()
    29  
    30  	l.writer.ReadLogs(config, watcher)
    31  
    32  	l.mu.Lock()
    33  	delete(l.readers, watcher)
    34  	l.mu.Unlock()
    35  }
    36  
    37  func decodeLogLine(dec *json.Decoder, l *jsonlog.JSONLog) (*logger.Message, error) {
    38  	l.Reset()
    39  	if err := dec.Decode(l); err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	var attrs []backend.LogAttr
    44  	if len(l.Attrs) != 0 {
    45  		attrs = make([]backend.LogAttr, 0, len(l.Attrs))
    46  		for k, v := range l.Attrs {
    47  			attrs = append(attrs, backend.LogAttr{Key: k, Value: v})
    48  		}
    49  	}
    50  	msg := &logger.Message{
    51  		Source:    l.Stream,
    52  		Timestamp: l.Created,
    53  		Line:      []byte(l.Log),
    54  		Attrs:     attrs,
    55  	}
    56  	return msg, nil
    57  }
    58  
    59  // decodeFunc is used to create a decoder for the log file reader
    60  func decodeFunc(rdr io.Reader) func() (*logger.Message, error) {
    61  	l := &jsonlog.JSONLog{}
    62  	dec := json.NewDecoder(rdr)
    63  	return func() (msg *logger.Message, err error) {
    64  		for retries := 0; retries < maxJSONDecodeRetry; retries++ {
    65  			msg, err = decodeLogLine(dec, l)
    66  			if err == nil {
    67  				break
    68  			}
    69  
    70  			// try again, could be due to a an incomplete json object as we read
    71  			if _, ok := err.(*json.SyntaxError); ok {
    72  				dec = json.NewDecoder(rdr)
    73  				retries++
    74  				continue
    75  			}
    76  
    77  			// io.ErrUnexpectedEOF is returned from json.Decoder when there is
    78  			// remaining data in the parser's buffer while an io.EOF occurs.
    79  			// If the json logger writes a partial json log entry to the disk
    80  			// while at the same time the decoder tries to decode it, the race condition happens.
    81  			if err == io.ErrUnexpectedEOF {
    82  				reader := io.MultiReader(dec.Buffered(), rdr)
    83  				dec = json.NewDecoder(reader)
    84  				retries++
    85  			}
    86  		}
    87  		return msg, err
    88  	}
    89  }