github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/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 // import "github.com/docker/docker/daemon/logger/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 tag string // tag values requested by the user to log 31 } 32 33 func init() { 34 if err := logger.RegisterLogDriver(Name, New); err != nil { 35 logrus.Fatal(err) 36 } 37 if err := logger.RegisterLogOptValidator(Name, ValidateLogOpt); err != nil { 38 logrus.Fatal(err) 39 } 40 } 41 42 // New creates new JSONFileLogger which writes to filename passed in 43 // on given context. 44 func New(info logger.Info) (logger.Logger, error) { 45 var capval int64 = -1 46 if capacity, ok := info.Config["max-size"]; ok { 47 var err error 48 capval, err = units.FromHumanSize(capacity) 49 if err != nil { 50 return nil, err 51 } 52 } 53 var maxFiles = 1 54 if maxFileString, ok := info.Config["max-file"]; ok { 55 var err error 56 maxFiles, err = strconv.Atoi(maxFileString) 57 if err != nil { 58 return nil, err 59 } 60 if maxFiles < 1 { 61 return nil, fmt.Errorf("max-file cannot be less than 1") 62 } 63 } 64 65 attrs, err := info.ExtraAttributes(nil) 66 if err != nil { 67 return nil, err 68 } 69 70 // no default template. only use a tag if the user asked for it 71 tag, err := loggerutils.ParseLogTag(info, "") 72 if err != nil { 73 return nil, err 74 } 75 if tag != "" { 76 attrs["tag"] = tag 77 } 78 79 var extra []byte 80 if len(attrs) > 0 { 81 var err error 82 extra, err = json.Marshal(attrs) 83 if err != nil { 84 return nil, err 85 } 86 } 87 88 buf := bytes.NewBuffer(nil) 89 marshalFunc := func(msg *logger.Message) ([]byte, error) { 90 if err := marshalMessage(msg, extra, buf); err != nil { 91 return nil, err 92 } 93 b := buf.Bytes() 94 buf.Reset() 95 return b, nil 96 } 97 98 writer, err := loggerutils.NewLogFile(info.LogPath, capval, maxFiles, marshalFunc, decodeFunc) 99 if err != nil { 100 return nil, err 101 } 102 103 return &JSONFileLogger{ 104 writer: writer, 105 readers: make(map[*logger.LogWatcher]struct{}), 106 tag: tag, 107 }, nil 108 } 109 110 // Log converts logger.Message to jsonlog.JSONLog and serializes it to file. 111 func (l *JSONFileLogger) Log(msg *logger.Message) error { 112 l.mu.Lock() 113 err := l.writer.WriteLogEntry(msg) 114 l.mu.Unlock() 115 return err 116 } 117 118 func marshalMessage(msg *logger.Message, extra json.RawMessage, buf *bytes.Buffer) error { 119 logLine := msg.Line 120 if !msg.Partial { 121 logLine = append(msg.Line, '\n') 122 } 123 err := (&jsonlog.JSONLogs{ 124 Log: logLine, 125 Stream: msg.Source, 126 Created: msg.Timestamp, 127 RawAttrs: extra, 128 }).MarshalJSONBuf(buf) 129 if err != nil { 130 return errors.Wrap(err, "error writing log message to buffer") 131 } 132 err = buf.WriteByte('\n') 133 return errors.Wrap(err, "error finalizing log buffer") 134 } 135 136 // ValidateLogOpt looks for json specific log options max-file & max-size. 137 func ValidateLogOpt(cfg map[string]string) error { 138 for key := range cfg { 139 switch key { 140 case "max-file": 141 case "max-size": 142 case "labels": 143 case "env": 144 case "env-regex": 145 case "tag": 146 default: 147 return fmt.Errorf("unknown log opt '%s' for json-file log driver", key) 148 } 149 } 150 return nil 151 } 152 153 // Close closes underlying file and signals all readers to stop. 154 func (l *JSONFileLogger) Close() error { 155 l.mu.Lock() 156 l.closed = true 157 err := l.writer.Close() 158 for r := range l.readers { 159 r.Close() 160 delete(l.readers, r) 161 } 162 l.mu.Unlock() 163 return err 164 } 165 166 // Name returns name of this logger. 167 func (l *JSONFileLogger) Name() string { 168 return Name 169 }