github.com/LazyboyChen7/engine@v17.12.1-ce-rc2+incompatible/daemon/logger/logentries/logentries.go (about) 1 // Package logentries provides the log driver for forwarding server logs 2 // to logentries endpoints. 3 package logentries 4 5 import ( 6 "fmt" 7 "strconv" 8 9 "github.com/bsphere/le_go" 10 "github.com/docker/docker/daemon/logger" 11 "github.com/pkg/errors" 12 "github.com/sirupsen/logrus" 13 ) 14 15 type logentries struct { 16 tag string 17 containerID string 18 containerName string 19 writer *le_go.Logger 20 extra map[string]string 21 lineOnly bool 22 } 23 24 const ( 25 name = "logentries" 26 token = "logentries-token" 27 lineonly = "line-only" 28 ) 29 30 func init() { 31 if err := logger.RegisterLogDriver(name, New); err != nil { 32 logrus.Fatal(err) 33 } 34 if err := logger.RegisterLogOptValidator(name, ValidateLogOpt); err != nil { 35 logrus.Fatal(err) 36 } 37 } 38 39 // New creates a logentries logger using the configuration passed in on 40 // the context. The supported context configuration variable is 41 // logentries-token. 42 func New(info logger.Info) (logger.Logger, error) { 43 logrus.WithField("container", info.ContainerID). 44 WithField("token", info.Config[token]). 45 WithField("line-only", info.Config[lineonly]). 46 Debug("logging driver logentries configured") 47 48 log, err := le_go.Connect(info.Config[token]) 49 if err != nil { 50 return nil, errors.Wrap(err, "error connecting to logentries") 51 } 52 var lineOnly bool 53 if info.Config[lineonly] != "" { 54 if lineOnly, err = strconv.ParseBool(info.Config[lineonly]); err != nil { 55 return nil, errors.Wrap(err, "error parsing lineonly option") 56 } 57 } 58 return &logentries{ 59 containerID: info.ContainerID, 60 containerName: info.ContainerName, 61 writer: log, 62 lineOnly: lineOnly, 63 }, nil 64 } 65 66 func (f *logentries) Log(msg *logger.Message) error { 67 if !f.lineOnly { 68 data := map[string]string{ 69 "container_id": f.containerID, 70 "container_name": f.containerName, 71 "source": msg.Source, 72 "log": string(msg.Line), 73 } 74 for k, v := range f.extra { 75 data[k] = v 76 } 77 ts := msg.Timestamp 78 logger.PutMessage(msg) 79 f.writer.Println(f.tag, ts, data) 80 } else { 81 line := string(msg.Line) 82 logger.PutMessage(msg) 83 f.writer.Println(line) 84 } 85 return nil 86 } 87 88 func (f *logentries) Close() error { 89 return f.writer.Close() 90 } 91 92 func (f *logentries) Name() string { 93 return name 94 } 95 96 // ValidateLogOpt looks for logentries specific log option logentries-address. 97 func ValidateLogOpt(cfg map[string]string) error { 98 for key := range cfg { 99 switch key { 100 case "env": 101 case "env-regex": 102 case "labels": 103 case "tag": 104 case key: 105 default: 106 return fmt.Errorf("unknown log opt '%s' for logentries log driver", key) 107 } 108 } 109 110 if cfg[token] == "" { 111 return fmt.Errorf("Missing logentries token") 112 } 113 114 return nil 115 }