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 }