github.com/LazyboyChen7/engine@v17.12.1-ce-rc2+incompatible/daemon/logger/jsonfilelog/jsonfilelog.go (about) 1 // Package jsonfilelog provides the default Logger implementation for 2 // Docker logging. This logger logs to files on the host server in the 3 // JSON format. 4 package jsonfilelog 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "fmt" 10 "strconv" 11 "sync" 12 13 "github.com/docker/docker/daemon/logger" 14 "github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog" 15 "github.com/docker/docker/daemon/logger/loggerutils" 16 units "github.com/docker/go-units" 17 "github.com/pkg/errors" 18 "github.com/sirupsen/logrus" 19 ) 20 21 // Name is the name of the file that the jsonlogger logs to. 22 const Name = "json-file" 23 24 // JSONFileLogger is Logger implementation for default Docker logging. 25 type JSONFileLogger struct { 26 mu sync.Mutex 27 closed bool 28 writer *loggerutils.LogFile 29 readers map[*logger.LogWatcher]struct{} // stores the active log followers 30 } 31 32 func init() { 33 if err := logger.RegisterLogDriver(Name, New); err != nil { 34 logrus.Fatal(err) 35 } 36 if err := logger.RegisterLogOptValidator(Name, ValidateLogOpt); err != nil { 37 logrus.Fatal(err) 38 } 39 } 40 41 // New creates new JSONFileLogger which writes to filename passed in 42 // on given context. 43 func New(info logger.Info) (logger.Logger, error) { 44 var capval int64 = -1 45 if capacity, ok := info.Config["max-size"]; ok { 46 var err error 47 capval, err = units.FromHumanSize(capacity) 48 if err != nil { 49 return nil, err 50 } 51 } 52 var maxFiles = 1 53 if maxFileString, ok := info.Config["max-file"]; ok { 54 var err error 55 maxFiles, err = strconv.Atoi(maxFileString) 56 if err != nil { 57 return nil, err 58 } 59 if maxFiles < 1 { 60 return nil, fmt.Errorf("max-file cannot be less than 1") 61 } 62 } 63 64 var extra []byte 65 attrs, err := info.ExtraAttributes(nil) 66 if err != nil { 67 return nil, err 68 } 69 if len(attrs) > 0 { 70 var err error 71 extra, err = json.Marshal(attrs) 72 if err != nil { 73 return nil, err 74 } 75 } 76 77 buf := bytes.NewBuffer(nil) 78 marshalFunc := func(msg *logger.Message) ([]byte, error) { 79 if err := marshalMessage(msg, extra, buf); err != nil { 80 return nil, err 81 } 82 b := buf.Bytes() 83 buf.Reset() 84 return b, nil 85 } 86 87 writer, err := loggerutils.NewLogFile(info.LogPath, capval, maxFiles, marshalFunc, decodeFunc) 88 if err != nil { 89 return nil, err 90 } 91 92 return &JSONFileLogger{ 93 writer: writer, 94 readers: make(map[*logger.LogWatcher]struct{}), 95 }, nil 96 } 97 98 // Log converts logger.Message to jsonlog.JSONLog and serializes it to file. 99 func (l *JSONFileLogger) Log(msg *logger.Message) error { 100 l.mu.Lock() 101 err := l.writer.WriteLogEntry(msg) 102 l.mu.Unlock() 103 return err 104 } 105 106 func marshalMessage(msg *logger.Message, extra json.RawMessage, buf *bytes.Buffer) error { 107 logLine := msg.Line 108 if !msg.Partial { 109 logLine = append(msg.Line, '\n') 110 } 111 err := (&jsonlog.JSONLogs{ 112 Log: logLine, 113 Stream: msg.Source, 114 Created: msg.Timestamp, 115 RawAttrs: extra, 116 }).MarshalJSONBuf(buf) 117 if err != nil { 118 return errors.Wrap(err, "error writing log message to buffer") 119 } 120 err = buf.WriteByte('\n') 121 return errors.Wrap(err, "error finalizing log buffer") 122 } 123 124 // ValidateLogOpt looks for json specific log options max-file & max-size. 125 func ValidateLogOpt(cfg map[string]string) error { 126 for key := range cfg { 127 switch key { 128 case "max-file": 129 case "max-size": 130 case "labels": 131 case "env": 132 case "env-regex": 133 default: 134 return fmt.Errorf("unknown log opt '%s' for json-file log driver", key) 135 } 136 } 137 return nil 138 } 139 140 // LogPath returns the location the given json logger logs to. 141 func (l *JSONFileLogger) LogPath() string { 142 return l.writer.LogPath() 143 } 144 145 // Close closes underlying file and signals all readers to stop. 146 func (l *JSONFileLogger) Close() error { 147 l.mu.Lock() 148 l.closed = true 149 err := l.writer.Close() 150 for r := range l.readers { 151 r.Close() 152 delete(l.readers, r) 153 } 154 l.mu.Unlock() 155 return err 156 } 157 158 // Name returns name of this logger. 159 func (l *JSONFileLogger) Name() string { 160 return Name 161 }