github.com/mheon/docker@v0.11.2-0.20150922122814-44f47903a831/daemon/logger/journald/journald.go (about) 1 // +build linux 2 3 // Package journald provides the log driver for forwarding server logs 4 // to endpoints that receive the systemd format. 5 package journald 6 7 import ( 8 "fmt" 9 "sync" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/coreos/go-systemd/journal" 13 "github.com/docker/docker/daemon/logger" 14 ) 15 16 const name = "journald" 17 18 type journald struct { 19 vars map[string]string // additional variables and values to send to the journal along with the log message 20 readers readerList 21 } 22 23 type readerList struct { 24 mu sync.Mutex 25 readers map[*logger.LogWatcher]*logger.LogWatcher 26 } 27 28 func init() { 29 if err := logger.RegisterLogDriver(name, New); err != nil { 30 logrus.Fatal(err) 31 } 32 if err := logger.RegisterLogOptValidator(name, validateLogOpt); err != nil { 33 logrus.Fatal(err) 34 } 35 } 36 37 // New creates a journald logger using the configuration passed in on 38 // the context. 39 func New(ctx logger.Context) (logger.Logger, error) { 40 if !journal.Enabled() { 41 return nil, fmt.Errorf("journald is not enabled on this host") 42 } 43 // Strip a leading slash so that people can search for 44 // CONTAINER_NAME=foo rather than CONTAINER_NAME=/foo. 45 name := ctx.ContainerName 46 if name[0] == '/' { 47 name = name[1:] 48 } 49 vars := map[string]string{ 50 "CONTAINER_ID": ctx.ContainerID[:12], 51 "CONTAINER_ID_FULL": ctx.ContainerID, 52 "CONTAINER_NAME": name} 53 return &journald{vars: vars, readers: readerList{readers: make(map[*logger.LogWatcher]*logger.LogWatcher)}}, nil 54 } 55 56 // We don't actually accept any options, but we have to supply a callback for 57 // the factory to pass the (probably empty) configuration map to. 58 func validateLogOpt(cfg map[string]string) error { 59 for key := range cfg { 60 switch key { 61 default: 62 return fmt.Errorf("unknown log opt '%s' for journald log driver", key) 63 } 64 } 65 return nil 66 } 67 68 func (s *journald) Log(msg *logger.Message) error { 69 if msg.Source == "stderr" { 70 return journal.Send(string(msg.Line), journal.PriErr, s.vars) 71 } 72 return journal.Send(string(msg.Line), journal.PriInfo, s.vars) 73 } 74 75 func (s *journald) Name() string { 76 return name 77 }